https://juejin.cn/post/7325069743143157801

在Java语言中,使用枚举(Enumerations)来实现单例模式被认为是最简洁、安全的方法之一。枚举类型的单例实现可以避免多线程同步问题,还能防止反序列化重新创建新的对象,同时写法简洁。

这里有几个原因让枚举成为实现单例的最佳方法:

  1. 线程安全:Java 虚拟机在加载枚举类的时候会使用类加载机制,保证枚举实例的唯一性和线程安全性。
  2. 写法简单:不需要自己去编写用来保证单例的代码。
  3. 防止反序列化创建新的实例:媒介的反序列化会通过java.lang.EnumvalueOf() 方法来返回枚举常量,而不是创建新的实例。
  4. 防止反射攻击:枚举类的构造函数默认是私有的,反射不能够用来创建枚举类型实例的新对象。

下面是使用枚举实现单例的一个典型例子:

public enum Singleton {
	INStANCE;
	
	public void doSomething() {
        // Perform operation here
    }

}

使用时非常简单:

public class SingletonDemo {
    public static void main(String[] args) {
        Singleton.INSTANCE.doSomething();
    }
}

在这个例子中,Singleton类型有一个名为INSTANCE的枚举常量,它代表了 Singleton 的唯一实例。你可以通过Singleton.INSTANCE来访问单例,这种方法是完全线程安全的,并且在任何情况下,都不可能创建出另一个Singleton实例。

这种方法在Java 1.5之后被广泛认可为实现单例的最佳方法,尤其是当单例需要通过序列化传输或者在高并发场景下使用时。在枚举单例的实现中,只有一个枚举常量INSTANCE,JVM会保证该实例的唯一性。不同于其他方法,枚举类型的单例模式无需担心序列化和反射的问题。