谈及Java单例模式,开发者通常都不会陌生。饿汉式、懒汉式、双重检测锁、静态内部类以及枚举——实现方式可谓丰富多样。今天,我们将重点聚焦枚举方式,这一方案在《Effective Java》中被强烈推荐,确实具备独特的优势。

一、案例演示
先提供一个最直观的用法示例,三步即可完成,清晰易懂。1、定义接口类
public interface MySingleton {
void doSomething();
}
2、创建枚举类并实现接口
public enum Singleton implements MySingleton {
INSTANCE {
@Override
public void doSomething() {
System.out.println("执行方法。。。");
}
}
}
3、运行测试
public class Test {
public static void main(String[] args) {
Singleton.INSTANCE.doSomething();
}
}
这便是枚举实现单例最基础的形式。简洁明了,无需繁琐的锁机制或条件判断。
二、深入扩展
仅仅掌握用法还不够,我们需要理解其优势,以及与其他实现方式的对比。1、枚举方式实现单例的优势
枚举单例最大的亮点在于:天然线程安全,且能彻底防止反射和序列化破坏。无需手动编写synchronized代码,也不必担心反序列化时产生新实例。Java虚拟机从底层保证了枚举实例的唯一性,比依赖代码防御的方式更为可靠。
2、五种实现方式的对比
- 饿汉式:类加载时即创建实例,线程安全,调用效率高,但无法实现延迟加载。若单例对象较重且未被使用,会造成内存浪费。
- 懒汉式:首次调用时才创建实例,支持延迟加载,但为保障线程安全需添加synchronized,调用效率较低。在高并发场景下性能表现不佳。
- 静态内部类方式:同样支持延迟加载,利用类加载机制确保线程安全,资源利用率高,是一种较为优雅的方案。
- 双重检测锁方式:看似完善,但由于JVM底层指令重排等问题,偶尔会出现BUG,实际开发中不建议采用。
- 枚举式(推荐):线程安全,调用效率高,但无法延迟加载。好在大多数场景下单例对象并不庞大,延迟加载的需求并不迫切。
3、总结
1. 饿汉式线程安全,调用效率高,但不能延迟加载。
2. 懒汉式线程安全,调用效率不高,能延迟加载。
3. 双重检测锁式由于JVM底层内部模型原因,偶尔会出问题。不建议使用。
4. 静态内部类式线程安全,资源利用率高,可以延时加载。
5. 枚举单例线程安全,调用效率高,但不能延迟加载。
4、如何选择?
没有银弹,需根据实际场景决定:
- 若单例对象占用资源少,无需延时加载:枚举式 优于 饿汉式。枚举的防破坏能力更强。
- 若单例对象占用资源大,需要延时加载:静态内部类式 优于 懒汉式。静态内部类兼顾了延迟加载与性能。
以上是对枚举单例的梳理总结。在实际项目中,根据资源需求与代码风格选择合适的实现方式即可。
