https://blog.csdn.net/qq_38844728/article/details/88903939
一.为什么使用枚举
单例的枚举实现在Effective Java一书中提到。因为其功能完善,使用简介,无偿地提供了序列化机制,在面对复杂的序列化或者反射攻击时任然可以绝对防止多次实例化等优点,被作者所推崇。
二.代码体现
模拟一个数据库连接类
public enum DataSourceEnum {
DATASOURCE;
private DBConnection connection = null;
private DataSourceEnum(){
connection = new DBConnection();//构造方法中new要单例的对象
}
public DBConnection getConnection(){
return connection;
}
}
1
2
3
4
5
6
7
8
9
10
public class DBConnection {
}
1
2
public class Test {
public static void main(String[] args) {
DBConnection conn1 = DataSourceEnum.DATASOURCE.getConnection();
DBConnection conn2 = DataSourceEnum.DATASOURCE.getConnection();
System.out.println(conn1 == conn2);
}
}
1
2
3
4
5
6
7
输出结果为true。
可以看一下DataSourceEnum类的反编译代码
public final class DataSourceEnum extends Enum
{
public static DataSourceEnum[] values(){
return (DataSourceEnum[])$VALUES.clone();
}
//toString的逆方法,返回指定名字,给定类的枚举常量
public static DataSourceEnum valueOf(String name){
return (DataSourceEnum)Enum.valueOf(creational/singleton/dbconn/DataSourceEnum, name);
}
//私有构造函数,参数有 此枚举常量的名称,枚举常量的序号
private DataSourceEnum(String s, int i){
super(s, i);
//单例对象的属性
connection = null;
connection = new DBConnection();
}
public DBConnection getConnection(){
return connection;
}
//单例对象
public static final DataSourceEnum DATASOURCE;
//单例对象的属性
private DBConnection connection;
private static final DataSourceEnum $VALUES[];
static
{
//与饿汉式相似,类初始化时创建单例对象
DATASOURCE = new DataSourceEnum("DATASOURCE", 0);
$VALUES = (new DataSourceEnum[] {
DATASOURCE
});
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Java规范字规定,每个枚举类型及其定义的枚举变量在JVM中都是唯一的,因此在枚举类型的序列化和反序列化上,Java做了特殊的规定。在序列化的时候Java仅仅是将枚举对象的name属性输到结果中,反序列化的时候则是通过java.lang.Enum的valueOf()方法来根据名字查找枚举对象。也就是说,序列化的时候只将DATASOURCE这个名称输出,反序列化的时候再通过这个名称,查找对应的枚举类型,因此反序列化后的实例也会和之前被序列化的对象实例相同。
————————————————
版权声明:本文为CSDN博主「宏志有缘再见」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_38844728/article/details/88903939