静态内部类 holder 写法是 java 中实现线程安全、懒加载单例的推荐方式,利用 jvm 类加载机制保证初始化线程安全,无需 synchronized 或 volatile;外部类加载时不初始化 holder,仅首次访问 holder.instance 时触发其线程安全的初始化。

静态内部类 Holder 写法是 Java 中实现线程安全、懒加载单例的推荐方式,核心在于利用 JVM 类加载机制保证初始化线程安全,且不依赖 synchronized 或 volatile。
为什么用静态内部类?
外部类(如 Singleton)在首次主动使用时才会被加载,但其静态内部类不会随外部类一起加载;只有当第一次访问该静态内部类的静态成员(比如 INSTANCE)时,JVM 才会触发它的初始化。这个过程由 JVM 保证线程安全,天然避免了双重检查锁的复杂性和潜在问题。
标准写法结构
典型的 Holder 单例包含三部分:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 私有构造方法:防止外部 new 实例
- 静态内部类 Holder:仅含一个 public static final 的实例字段
- 公共静态获取方法:返回 Holder.INSTANCE
示例代码:
public class Singleton {
private Singleton() {} // 私有构造,禁止外部实例化
private static class Holder {
static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return Holder.INSTANCE; // 触发 Holder 类初始化
}
}
关键细节说明
这种写法能同时满足三个重要目标:
- 懒加载:getInstance() 第一次调用时才创建实例,不是类加载时就初始化
- 线程安全:JVM 对类初始化加了隐式锁,多线程调用 getInstance() 不会出现重复初始化
- 无同步开销:后续调用直接读取静态字段,不涉及任何锁或 volatile 读写
注意事项
虽然简洁高效,但需注意几点:
- 不能在 Holder 类中做复杂逻辑或抛出异常的初始化,否则类加载失败会导致 NoClassDefFoundError
- 如果单例依赖外部资源(如配置、Spring 上下文),需确保 Holder 初始化时机符合预期
- 反射仍可绕过私有构造(可通过构造方法内加判断规避,但非本写法重点)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










