用Enum实现Singleton(用Java)

我读过,可以使用Enum来实现Java中的Singleton ,例如:

 public enum MySingleton { INSTANCE; } 

但是,上述工作如何? 具体来说,一个Object必须被实例化。 在这里, MySingleton如何被实例化? 谁在做new MySingleton()

这个,

 public enum MySingleton { INSTANCE; } 

有一个隐含的空构造函数。 让我们来明确一点,

 public enum MySingleton { INSTANCE; private MySingleton() { System.out.println("Here"); } } 

如果你用类似main()方法添加了另一个类

 public static void main(String[] args) { System.out.println(MySingleton.INSTANCE); } 

你会看到的

 Here INSTANCE 

enum字段是编译时间常量,但它们是enumtypes的实例。 而且,它们是在第一次引用枚举types时构造的。

在Joshua Bloch的Java最佳实践书中 ,你可以find解释为什么你应该使用私有构造函数或Enumtypes来强制实现Singleton属性。 这一章很长,所以总结一下:

将一个类作为一个Singleton可以使得testing它的客户端变得困难,因为除非它实现了一个types的接口,否则不可能用一个单例替代一个模拟实现。 推荐的方法是通过简单地使用一个元素来枚举types来实现单例:

 // Enum singleton - the preferred approach public enum Elvis { INSTANCE; public void leaveTheBuilding() { ... } } 

这种方法在function上等同于公共领域的方法,除了它更简洁,提供了免费的序列化机制,并且提供了对多重实例化的铁证,即使面对复杂的序列化或reflection攻击。

虽然这种方法尚未被广泛采用,但是单元枚举types是实现单例的最好方法。

enumtypes是一种特殊的classtypes。

你的enum声明实际上编译成类似的东西

 public final class MySingleton { public final static MySingleton INSTANCE = new MySingleton(); } 

当你的代码首先访问INSTANCEMySingleton类将被JVM加载和初始化。 这个过程初始化一次 (懒惰)的static字段。

像所有枚举实例一样,Java在加载类时实例化每个对象,并保证每个JVM仅实例化一次。 将INSTANCE声明看作公共静态最终字段:Java将在第一次引用类时实例化对象。

这些实例是在静态初始化过程中创build的,这在Java语言规范第12.4节中定义。

对于什么是值得的, Joshua Bloch详细描述了这个模式,作为Effective Java Second Edition的第 3项。

由于Singleton模式是关于有一个私人的构造函数,并调用一些方法来控制实例(如一些getInstance ),在枚举中,我们已经有一个隐式的私有构造函数。

我不完全知道如何JVM或一些容器控制我们的Enums实例,但它似乎已经使用隐式Singleton Pattern ,不同之处是我们不调用getInstance ,我们只是调用枚举。

 enum Checks { INSTANCE; Checks() { System.out.println("checks"); } public void dowork() { System.out.println(" do work please "); } } public class EnumSingelton { public static void main(String[] args) { Checks.INSTANCE.dowork(); } }