枚举单例最简写法为public enum Singleton { INSTANCE; },JVM保证其初始化原子线程安全、反射不可创建新实例、序列化返回唯一对象,支持字段方法但非严格懒加载。

枚举单例的写法就三行
Java 中用枚举实现单例,最简写法只需要定义一个枚举类,里面声明一个常量:
- public enum Singleton { INSTANCE; }
- INSTANCE 就是唯一的实例,JVM 在类加载阶段自动创建,且只创建一次
- 后续所有获取方式都是 Singleton.INSTANCE,返回的永远是同一个对象引用
为什么多线程下天然安全
枚举单例不需要加锁、也不依赖 volatile 或 synchronized,就能在并发场景下绝对安全,原因全在 JVM 层面:
- JVM 保证枚举类型的初始化是原子且线程安全的——多个线程同时首次访问 Singleton.class 时,只会有一个线程执行初始化,其余阻塞等待
- 枚举构造器被 JVM 特殊保护,反射调用
Constructor.newInstance()会直接抛IllegalArgumentException,无法绕过创建新实例 - 枚举类默认可序列化,反序列化时 JVM 强制返回已存在的 INSTANCE,不会生成新对象,无需手动实现
readResolve()
可以加字段和方法,不影响安全性
INSTANCE 不仅是个占位符,它本身就是一个完整对象,支持添加状态和行为:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 可定义私有字段,比如
private String config = "prod"; - 可添加 public 方法,如
public void init() { ... }或public String getConfig() { return config; } - 所有线程通过 INSTANCE 调用方法,操作的是同一份数据,无同步冲突
注意它不是懒加载
枚举单例在类第一次被主动使用(如访问 INSTANCE 或调用其方法)时触发初始化,属于“按需加载”,但不是严格意义上的延迟到 getInstance() 调用才初始化——因为 INSTANCE 是 static final 的,加载即实例化。
立即学习“Java免费学习笔记(深入)”;
如果业务要求启动时不加载(例如单例依赖外部资源且可能失败),枚举就不适合;否则,它比双重检查锁、静态内部类更简洁、更可靠。

















