面试官:请写一个你认为比较“完美”的单例 (3)

枚举实际是通过一个继承自Enum的final类来实现(通过反编译class文件可看到具体实现),在static代码块中对其成员进行初始化,因此借助类加载机制来保障其线程安全

枚举是不支持通过反射实例化的,在Constructor类的newInstance方法中可看到

if ((clazz.getModifiers() & Modifier.ENUM) != 0) throw new IllegalArgumentException("Cannot reflectively create enum objects");

枚举在序列化的时候仅仅是将枚举对象的name属性输出到结果中,反序列化的时候则是通过java.lang.Enum的valueOf方法来根据名字查找枚举对象。并且,编译器是不允许任何对这种序列化机制的定制的,禁用了writeObject、readObject、readObjectNoData、writeReplace和readResolve等方法。枚举通过这种机制保障了序列化安全。

总结

枚举方案近乎“完美”,但实际中,大部分情况下,我们使用双重检查锁方案或静态内部类方案基本都能满足我们的场景并能很好地运行。并且方案从来没有“完美”,只有更好或更合适。本文只是从单例实现的不断演进的过程中,了解或回顾如反射、序列化、线程安全、Java内存模型(volatile语义)、JVM类加载机制、JVM指令重排序优化等方面的知识,同时也是启示我们在设计或实现的过程中,多从各个角度思考,尽可能全面地考虑问题。或者,在相关面试中能更好地迎合面试官的“完美”期望。

作者:雨歌,一枚仍在学习路上的IT老兵
欢迎关注作者公众号:半路雨歌,一起学习成长

qrcode

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wspwxz.html