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 @Override15 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/