一、为什么使用枚举

什么时候应该使用枚举呢?每当需要一组固定的常量的时候,如一周的天数、一年四季等。或者是在我们编译前就知道其包含的所有值的集合。

利用 public final static 完全可以实现的功能,为什么要使用枚举?
public class Season { public static final int SPRING = 1; public static final
int SUMMER = 2; public static final int AUTUMN = 3; public static final int
WINTER = 4; }
(1)安全性。这种模式不是类型安全的。比如说我们设计一个函数,要求传入春夏秋冬的某个值。但是使用int类型,我们无法保证传入的值为合法。如:传入5。


(2)可读性。我们需要方便得到枚举类型的字符串表达式。int常量打印出来,我们所见到的就是一组数字,没什么用;String常量可以打印出详细信息,但是字符串的比较操作性能较低。

二、枚举的几种使用方式

用法一:常量
public enum Color { RED, GREEN, BLANK, YELLOW }
用法二:switch
enum Signal { GREEN, YELLOW, RED } public class TrafficLight { Signal color =
Signal.RED;public void change() { switch (color) { case RED: color =
Signal.GREEN;break; case YELLOW: color = Signal.RED; break; case GREEN: color =
Signal.YELLOW;break; } } }
用法三:向枚举中添加新方法
public enum Color { RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4
);// 成员变量 private String name; private int index; // 构造方法 private Color(String
name,int index) { this.name = name; this.index = index; } // 普通方法 public static
String getName(int index) { for (Color c : Color.values()) { if (c.getIndex() ==
index) {return c.name; } } return null; } // get set 方法 public String
getName() {return name; } public void setName(String name) { this.name = name; }
public int getIndex() { return index; } public void setIndex(int index) { this
.index = index; } }
用法四:覆盖枚举的方法
public enum Color { RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4
);// 成员变量 private String name; private int index; // 构造方法 private Color(String
name,int index) { this.name = name; this.index = index; } //覆盖方法 @Override
public String toString() { return this.index+"_"+this.name; } }
用法五:实现接口
public interface Behaviour { void print(); String getInfo(); } public enum
Colorimplements Behaviour{ RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3),
YELLO("黄色", 4); // 成员变量 private String name; private int index; // 构造方法 private
Color(String name,int index) { this.name = name; this.index = index; } //接口方法
@Overridepublic String getInfo() { return this.name; } //接口方法 @Override public
void print() { System.out.println(this.index+":"+this.name); } }
用法六:使用接口组织枚举
public interface Food { enum Coffee implements Food{
BLACK_COFFEE,DECAF_COFFEE,LATTE,CAPPUCCINO }enum Dessert implements Food{
FRUIT, CAKE, GELATO } }
三、原理(代码易懂,不做详细介绍)
enum Day { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY } //
反编译之后如下:// 反编译Day.class final class Day extends Enum { //编译器为我们添加的静态的values()方法
public static Day[] values() { return (Day[])$VALUES.clone(); } //
编译器为我们添加的静态的valueOf()方法,注意间接调用了Enum也类的valueOf方法 public static Day
valueOf(String s) {return (Day)Enum.valueOf(com/zejian/enumdemo/Day, s); } //
私有构造函数 private Day(String s, int i) { super(s, i); } //前面定义的7种枚举实例 public static
final Day MONDAY; public static final Day TUESDAY; public static final Day
WEDNESDAY;public static final Day THURSDAY; public static final Day FRIDAY;
public static final Day SATURDAY; public static final Day SUNDAY; private static
final Day $VALUES[]; static { //实例化枚举实例 MONDAY = new Day("MONDAY", 0); TUESDAY =
new Day("TUESDAY", 1); WEDNESDAY = new Day("WEDNESDAY", 2); THURSDAY = new
Day("THURSDAY", 3); FRIDAY = new Day("FRIDAY", 4); SATURDAY = new
Day("SATURDAY", 5); SUNDAY = new Day("SUNDAY", 6); $VALUES = (new Day[] {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY }); } }
四、枚举保证线程安全

由上面反编译代码可以看到,“ public static final Day
MONDAY; ”,static类型的属性会在类被加载之后被初始化,当一个Java类第一次被真正使用到的时候静态资源被初始化、Java类的加载和初始化过程都是线程安全的。所以,创建一个enum类型是线程安全的。

JVM类加载机制 <https://www.cnblogs.com/hexinwei1/p/9910638.html>中:

“ 并发:


  虚拟机会保证一个类的类构造器<clinit>()在多线程环境中被正确的加锁、同步,如果多个线程同时去初始化一个类,那么只会有一个线程去执行这个类的类构造器<clinit>(),其他线程都需要阻塞等待,直到活动线程执行<clinit>()方法完毕。


特别需要注意的是,在这种情形下,其他线程虽然会被阻塞,但如果执行<clinit>()方法的那条线程退出后,其他线程在唤醒之后不会再次进入/执行<clinit>()方法,因为
在同一个类加载器下,一个类型只会被初始化一次。 ”

 

 

参考资料 / 相关推荐:

Java 7 源码学习系列(二)——Enum <http://www.hollischuang.com/archives/92>

Java基础知识——枚举 <http://www.hollischuang.com/archives/2829>

深入理解Java枚举类型(enum)
<https://blog.csdn.net/javazejian/article/details/71333103#%E7%90%86%E8%A7%A3%E6%9E%9A%E4%B8%BE%E7%B1%BB%E5%9E%8B>

【JAVA】浅谈java枚举类 <https://www.cnblogs.com/sister/p/4700702.html>

Java 枚举(enum) 详解7种常见的用法
<https://blog.csdn.net/testcs_dn/article/details/78604547>

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:ixiaoyang8@qq.com
QQ群:637538335
关注微信