介绍
关于枚举类是什么我在这里就不重复做介绍了,本文的内容是剥开枚举表面的面纱,还原一个最真实最原始的枚举类 。
正文
首先我们来看一个最简单的枚举类的写法:
public enum EnumSingleton {
INSTANCE
}
说明:上面不仅是一个枚举类,还是一个单例的写法 。整个代码看起相当简洁,但就因为它的简洁,我们可能会好奇,这个枚举结构和我们的一般的类不同,但是却又能把他当做一个普通的类来用,那么他又是如何实现我们普通类的功能?
这里我们想到了一个思路,既然 java 文件最终都会编译成 class 文件然后载入内存去运行,按理来说,能跟普通类一样运行的枚举类,class 文件应该都相差不大,我们动手实践一下:
javac EnumSingleton.java
javap -c EnumSingleton
得到如下的代码:
public final class EnumSingleton extends java.lang.Enum<EnumSingleton> {
public static final EnumSingleton INSTANCE;
public static EnumSingleton[] values();
Code:
0: getstatic #1 // Field $VALUES:[LEnumSingleton;
3: invokevirtual #2 // Method "[LEnumSingleton;".clone:()Ljava/lang/Object;
6: checkcast #3 // class "[LEnumSingleton;"
9: areturn
public static EnumSingleton valueOf(java.lang.String);
Code:
0: ldc #4 // class EnumSingleton
2: aload_0
3: invokestatic #5 // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
6: checkcast #4 // class EnumSingleton
9: areturn
static {};
Code:
0: new #4 // class EnumSingleton
3: dup
4: ldc #7 // String INSTANCE
6: iconst_0
7: invokespecial #8 // Method "<init>":(Ljava/lang/String;I)V
10: putstatic #9 // Field INSTANCE:LEnumSingleton;
13: iconst_1
14: anewarray #4 // class EnumSingleton
17: dup
18: iconst_0
19: getstatic #9 // Field INSTANCE:LEnumSingleton;
22: aastore
23: putstatic #1 // Field $VALUES:[LEnumSingleton;
26: return
}
说明:经过我们对枚举类 class 文件的反编译,看到了许多不是我们自己写的代码,而且通过这个反编译的结果,大体的结构已经出来了,但是方法里面还是包含许多不易读懂的指令操作 。这还不是我们最终想要的结果,我们的目的是想办法将其还原成我们最熟悉的结构 。接下来我们继续使用 jad.exe 这个小工具将其还原(工具可以自行百度下载):
C:\Users\zoke\Desktop\jad.exe EnumSingleton.class
得到如下的代码:
public final class EnumSingleton extends Enum {
public static final EnumSingleton INSTANCE;
private static final EnumSingleton $VALUES[];
private EnumSingleton(String s, int i){
super(s, i);
}
public static EnumSingleton[] values(){
return (EnumSingleton[])$VALUES.clone();
}
public static EnumSingleton valueOf(String s){
return (EnumSingleton)Enum.valueOf(EnumSingleton, s);
}
static {
INSTANCE = new EnumSingleton("INSTANCE", 0);
$VALUES = (new EnumSingleton[] {INSTANCE});
}
}
结论与总结:到了这里已经非常简洁明了,我们写的枚举类,实际上还是继承的 Enum 类,同时也有着自己的构造方法 。这里面涉及到一个名称,那就是语法糖 。实际上枚举类的写法就是一个语法糖的体现 。那什么是语法糖呢,以 Java 语言举例,简单来说就是我们可以写一些非常简洁的代码(例如枚举),去实现一些原本需要很多代码才能实现的功能,而编译器在进行编译时,遇到这些语法糖,会将这些语法糖代码按照一定的规则编译成正常的 Java 语法结构的 class 文件,也就是说是编译器帮我们完成了剩下的工作,这对开发者和 JVM 来说都是无感知的,不会影响正常的运行性能,并且更易于读懂。语法糖在Java中的运用还有有 泛型与类型擦除、自动装箱与拆箱、变长参数、增强for循环、内部类 等 。也就是说枚举实际上编译后还是一个正常的 Java 类 。