怎样实现一个可靠的 Java 单例?
先说出你的答案
定义边界、关键机制、一个反例;P8题再补容量、失败与验证。
查看完整题解
参考回答
直接回答
若类型需求合适,枚举单例是简洁选择,语言及原生序列化机制会维护相应的枚举实例语义。普通类也可采用静态持有者实现延迟初始化。无论哪一种,“单例”都需限定到相应运行时类和类加载器,不能直接推导成多进程、多服务器只有一个对象。
讲清原理
安全创建与安全使用要分开:类初始化机制可以保证实例创建与发布的相应安全性,但单例内部可变字段的并发更新仍要自己设计。普通类的 private 构造器也不能自动解决所有反射、克隆和序列化路径。
例子与易错点
enum Registry { INSTANCE }
System.out.println(Registry.INSTANCE == Registry.valueOf("INSTANCE")); // true
不适合使用枚举时,下面是普通类的静态持有者写法;该代码块声明为外部类的静态成员:
static final class Singleton {
private Singleton() {}
private static class Holder {
static final Singleton INSTANCE = new Singleton();
}
static Singleton instance() { return Holder.INSTANCE; }
}
首次调用 instance() 并读取 Holder.INSTANCE 时,会触发 Holder 的初始化,不必自己拼装双重检查锁。若添加原生序列化或开放反射使用场景,需要重新审视普通类的唯一性边界。跨进程协调则是另一类系统问题。
相关题:第 33 题、第 43 题、第 44 题、第 51 题。
和评分标准对照,你能独立回答到哪一步?
自评会安排下一次复习,不保存你的口述内容。
这道题,你掌握得怎么样?
掌握程度由你主动标记,阅读和收藏不会自动改变状态。