用Enum实现Singleton(用Java)

问题

我已经读过可以使用aEnum在Java中实现Singleton,例如:

public enum MySingleton {
     INSTANCE;   
}

但是,上面的工作如何?具体来说,aObject必须实例化。在这里,MySingleton如何实例化?谁在做new MySingleton()


#1 热门回答(166 赞)

这个,

public enum MySingleton {
  INSTANCE;   
}

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

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

如果你然后添加另一个类与amain()方法类似

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

你会看到

Here
INSTANCE

enumfields是编译时常量,但它们是其enumtype的实例。并且,它们是在第一次引用枚举类型时构造的。


#2 热门回答(52 赞)

在Joshua Bloch的Java best practices book中,你可以找到为什么要使用私有构造函数或Enum类型强制执行Singleton属性的原因。这章很长,所以要总结一下:

使类成为单例可能会使测试其客户端变得困难,因为除非它实现了作为其类型的接口,否则不可能将模拟实现替换为单例。推荐的方法是通过简单地使用一个元素创建一个枚举类型来实现单例:

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

这种方法在功能上等同于公共字段方法,除了它更简洁,免费提供序列化机制,并提供防止多个实例化的铁定保证,即使面对复杂的序列化或反射攻击。

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


#3 热门回答(52 赞)

Anenumtype是一种特殊类型的4887991675type。

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

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

当你的代码首次访问INSTANCE时,类1715114071将由JVM加载并初始化。此过程初始化static字段高于882402943一次**(懒洋洋地)。