关于枚举类型的单例模式问题

来源:13-14 单例模式4

过客12

2020-02-02

老师,我有两个问题
1. 我在有的书上看见说,像您视频上那样写的会违反“单一职责”原则,需要把枚举类再封装在一个类里面,请问一下为什么呢?
2. 枚举类型的单例模式为什么可以防止被反序列化生成新的对象呢,除了使用这种方式防止被反序列化,还有没有其他方式防止被反序列化呢,比如静态内部类能防止反序列化吗,为什么呢?

写回答

1回答

悟空

2020-02-02

再封装一层,把枚举封装成类似于普通单例的样子,是可以的,但是我的写法也是没有问题的。

而对于序列化这件事情,Java专门对枚举的序列化做了规定,在序列化时仅仅是将枚举对象的name属性输出到结果中,反序列化的时候,就是通过java.lang.Enum的valueOf方法,来根据名字查找枚举对象,而不是创建新的对象,所以这就防止了反序列化导致的单例破坏问题的出现。

 

对于通过反射破坏单例而言,枚举类同样有防御措施。反射在通过newInstance创建对象时,会检查这个类是否是枚举类,如果是,就抛出 IllegalArgumentException("Cannot reflectively create enum objects") 异常,反射创建对象失败。

 

可以看出,枚举这种方式,能够防止序列化和反射破坏单例,在这一点上,与其他的实现方式比,有很大的优势。安全问题不容小视,一旦生成了多个实例,单例模式就彻底没用了。

 

所以结合讲到的这3个优点,写法简单、线程安全、防止反序列化和反射破坏单例,枚举写法最终胜出。

其他方式不能防止。


1
0

线程八大核心+Java并发原理及企业级并发解决方案

完整的并发知识网络+丰富的工作内容分享+50余道并发高频面试题

2512 学习 · 939 问题

查看课程