jdk5中加入了enum类型,那么他是怎样一种结构呢,通过反编译enum可以一窥。
1 public enum Status{ 2 OK, ERROR 3 }
反编译上述代码,可知enum在编译后被转换成了一个被public final修饰的、继承了java.lang.Enum的类型,看来enum只不过是一颗语法糖罢了。
OK、ERROR转换成了public static finally Status类型的类变量,还自动生成了一个public static Status[]类型的数组。
OK、ERROR既然是static final类型的,一定在声明处就赋了值,那么我们来看类初始化方法。如下图,可以看到在创建OK、ERROR时,调用了Status(String, int)构造器,这个构造器是java.lang.Enum中唯一的一个构造器,而此时我们并没有显示调用该构造器,这些都是编译期帮我们做的。
那么,如果我们自定义enum会是怎样一番景象呢?定义enum如下
1 public enum Status { 2 OK(1,"ok"), BAD(2,"bad"); 3 4 private int code; 5 private String msg; 6 private Status(int a, String b) { 7 this.code = a; 8 this.msg = b; 9 } 10 public int code() { 11 return code; 12 } 13 public String msg() { 14 return msg; 15 } 16 }
反编译后发现,与之前不同的地方只在于创建OK、ERROR时所调用的构造器,前例调用了java.lang.Enum的唯一构造器,本例所调用的构造器既不是Enum的唯一构造器Enum(String, int),也不是我们自定义的Status(int, String)构造器,而是二者融合后的一个构造器Status(String, int, int, String),但在class字节码中并没有该构造器的实现,并且自定义的Status构造器也没有出现。
通过以上分析可知,enum中的OK、ERROR其实就是Enum子类中的类变量,这些类变量在类初始化时通过调用特殊的构造器被赋值。由于java中是单继承的,让enum显示继承类是不可能了,但是可以实现接口。下例的代码中,SPECIAL实现了自己的StatusInterface接口,这也比较好理解,像SPECIAL(3, "special")这种写法,其实就是在调用(特殊的)构造器创建一个名为SPECIAL的类变量(SPECIAL这种写法与SPECIAL()等价),那么SPECIAL(3, "special"){...}其实就是实例化一个Status的代理类(子类)。
1 public enum Status implements StatusInterface{ 2 OK(1,"ok"), BAD(2,"bad"), SPECIAL(3, "special"){ 3 @Override 4 public void statusInterface() { 5 System.out.println("special status"); 6 } 7 }; 8 private int code; 9 private String msg; 10 private Status(int a, String b) { 11 this.code = a; 12 this.msg = b; 13 } 14 @Override 15 public void statusInterface() { 16 System.out.println("normal status"); 17 } 18 public int code() { 19 return code; 20 } 21 public String msg() { 22 return msg; 23 } 24 }
参考:https://unmi.cc/understand-java-enum-with-bytecode/