静态内部类单例通过JVM类初始化机制保证线程安全,无需显式同步;其核心是private static class SingletonHolder中定义final INSTANCE,并在getInstance()中首次引用触发懒加载。
为什么静态内部类能保证线程安全
因为 JVM 保证类的初始化是线程安全的,
类第一次被主动引用时才触发初始化,而这个“第一次”由 JVM 锁住,天然串行。不像双重检查锁(DCL)需要自己写
和
,这里连锁都不用显式加。
常见错误现象:有人把
写成
—— 这根本没用内部类,每次调用都新建实例;或者把
声明为 public,外部误触发加载,提前初始化。
必须是 private static class,且仅在
中被引用
外部代码不能通过反射或类加载器提前触碰
构造函数仍需设为 private,防止反射攻击(虽然静态内部类本身不防反射,但这是兜底)
静态内部类单例的标准写法
核心就三块:私有构造、静态内部类、对外暴露的
。没有多余字段,不依赖任何第三方工具类,JDK 1.2+ 全支持。
典型误用:在
里加静态代码块或复杂初始化逻辑——这会拖慢首次调用速度,且一旦抛异常,后续调用全失败(JVM 会标记该类初始化失败,再访问直接抛
)。
立即学习
“
Java免费学习笔记(深入)
”;
必须是
,否则可能被反射修改(虽概率低,但破坏单例语义)
不要在
中调用外部服务、读配置文件等耗时/可能失败的操作
如果真需要延迟初始化 + 复杂逻辑,应改用
或
配合 DCL
它和双重检查锁(DCL)比有什么实际差异
性能上几乎无差别(HotSpot 对静态初始化做了充分优化),但 DCL 的
字段写入在某些旧 JVM 或弱内存模型设备上仍有隐患;而静态内部类方案完全交给 JVM 保证,更“省心”。
Eclipse导入Android或其他的JAVA项目的正确方法 WORD版
本文档主要讲述的是Eclipse导入Android或其他的JAVA项目的正确方法;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看
下载
使用场景限制:DCL 可以配合参数构造(比如传入配置对象),静态内部类做不到——因为
是编译期确定的常量表达式,不能带运行时参数。
需要无参构造、纯内存态单例 → 优先选静态内部类
需要根据配置动态决定实例行为(如不同环境用不同实现)→ DCL 或枚举更合适
Android 低版本(4.0 以前)对类初始化顺序有 bug,曾导致静态内部类失效,现基本可忽略
容易被忽略的兼容性坑
最隐蔽的问题是:当单例类实现了
,反序列化会生成新对象,破坏单例。静态内部类方案对此毫无防护,必须手动补
。
另一个坑是模块化(Java 9+ Module System):如果
在 module A,而
被 module B 的类意外引用(比如日志框架扫描所有类),可能触发提前初始化。
必须加上
模块声明中避免
或
整个包给不信任的模块
单元测试里别用
,这会绕过 JVM 的懒加载保护
真正难的不是写对这十几行代码,而是想清楚“这个单例是否会被反射、序列化、模块系统、热部署工具干扰”——这些地方一漏,线程安全就只是假象。
SingletonHoldersynchronizedvolatilegetInstance()public static Singleton getInstance() { return new Singleton(); }SingletonHolderSingletonHoldergetInstance()SingletonHolder.classgetInstance()SingletonHolderNoClassDefFoundErrorpublic class Singleton {
private Singleton() {}
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}INSTANCEfinalSingletonHolderjava.util.concurrent.ConcurrentHashMapAtomicReferencevolatileINSTANCESerializablereadResolve()SingletonSingletonHolderprivate Object readResolve() { return getInstance(); }opensexportsClassLoader.loadClass("xxx.Singleton$SingletonHolder")