//当我们写下下列代码时:
public enum DataSourceEnum {
DATASOURCE;
}
使用java自带的反编译工具:
在命令行 中输入 javap -c DataSourceEnum.class 进行字节码文件查看,结果如下
Compiled from "DataSourceEnum.java"
public final class DataSourceEnum extends java.lang.Enum<DataSourceEnum> {
public static final DataSourceEnum DATASOURCE;
public static DataSourceEnum[] values();
Code:
0: getstatic #1 // Field $VALUES:[LDataSourceEnum;
3: invokevirtual #2 // Method "[LDataSourceEnum;".clone:()Ljava/lang/Object;
6: checkcast #3 // class "[LDataSourceEnum;"
9: areturn
public static DataSourceEnum valueOf(java.lang.String);
Code:
0: ldc #4 // class DataSourceEnum
2: aload_0
3: invokestatic #5 // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
6: checkcast #4 // class DataSourceEnum
9: areturn
static {};
Code:
0: new #4 // class DataSourceEnum
3: dup
4: ldc #7 // String DATASOURCE
6: iconst_0
7: invokespecial #8 // Method "<init>":(Ljava/lang/String;I)V
10: putstatic #9 // Field DATASOURCE:LDataSourceEnum;
13: iconst_1
14: anewarray #4 // class DataSourceEnum
17: dup
18: iconst_0
19: getstatic #9 // Field DATASOURCE:LDataSourceEnum;
22: aastore
23: putstatic #1 // Field $VALUES:[LDataSourceEnum;
26: return
}
使用反编译命令行工具jad 查看
输入jad -s java DataSourceEnum.class
得到提示:
Parsing DataSourceEnum.class... Generating DataSourceEnum.java
表示jad会将字节码文件,反向生成java文件,得到的java文件如下:
// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3)
// Source File Name: DataSourceEnum.java
public final class DataSourceEnum extends Enum
{
public static DataSourceEnum[] values()
{
return (DataSourceEnum[])$VALUES.clone();
}
public static DataSourceEnum valueOf(String s)
{
return (DataSourceEnum)Enum.valueOf(DataSourceEnum, s);
}
private DataSourceEnum(String s, int i)
{
super(s, i);
}
public static final DataSourceEnum DATASOURCE;
private static final DataSourceEnum $VALUES[];
static
{
DATASOURCE = new DataSourceEnum("DATASOURCE", 0);
$VALUES = (new DataSourceEnum[] {
DATASOURCE
});
}
}
由此可见java 中的枚举使用了语法糖,为我们省去的大量代码
所谓 语法糖(Syntactic Sugar),也称糖衣语法,是由英国计算机学家 Peter.J.Landin 发明的一个术语,指在计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是但是更方便程序员使用。只是在编译器上做了手脚,却没有提供对应的指令集来处理它。
由反编译后的代码可知,DATASOURCE 被声明为 static 的,根据类加载过程,可以知道虚拟机会保证一个类的初始化 方法在多线程环境中被正确的加锁、同步。所以,枚举实现是在实例化时是线程安全。
接下来看看序列化问题:
Java规范中规定,每一个枚举类型极其定义的枚举变量在JVM中都是唯一的,因此在枚举类型的序列化和反序列化上,Java做了特殊的规定。
在序列化的时候Java仅仅是将枚举对象的name属性输出到结果中,反序列化的时候则是通过 java.lang.Enum 的 valueOf() 方法来根据名字查找枚举对象。
也就是说,以下面枚举为例,序列化的时候只将 DATASOURCE 这个名称输出,反序列化的时候再通过这个名称,查找对于的枚举类型,因此反序列化后的实例也会和之前被序列化的对象实例相同。
当然在jdk1.8 中 如果对枚举类进行反射会跑出异常,也就是说对枚举类进行反射时连类装载的入口方法<init>()都没有了
java.lang.NoSuchMethodException: com.lin.Person$Singleton.<init>()
at java.lang.Class.getConstructor0(Class.java:3074)
at java.lang.Class.getDeclaredConstructor(Class.java:2170)
at com.lin.Person.main(Person.java:30)