何时应该使用枚举呢?每当须要一组固定的常量的时候,如一周的天数、一年四季等。或者是在咱们编译前就知道其包含的全部值的集合。html
利用 public final static 彻底能够实现的功能,为何要使用枚举?java
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 }
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 Color implements 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; } //接口方法 @Override public 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类加载机制中:ide
“ 并发:函数
虚拟机会保证一个类的类构造器<clinit>()在多线程环境中被正确的加锁、同步,若是多个线程同时去初始化一个类,那么只会有一个线程去执行这个类的类构造器<clinit>(),其余线程都须要阻塞等待,直到活动线程执行<clinit>()方法完毕。post
特别须要注意的是,在这种情形下,其余线程虽然会被阻塞,但若是执行<clinit>()方法的那条线程退出后,其余线程在唤醒以后不会再次进入/执行<clinit>()方法,由于在同一个类加载器下,一个类型只会被初始化一次。 ”性能