Java 如果不是惰性初始化,使用方法而不是静态类成员构建单例是否有任何优势?
我经常看到singleton是这样构建的:Java 如果不是惰性初始化,使用方法而不是静态类成员构建单例是否有任何优势?,java,Java,我经常看到singleton是这样构建的: public static MyClass instance() { if (singleton == null) { singleton = new MyClass(); } return singleton; } 如果不是因为延迟初始化的效果,这种方法比简单地声明这样的静态实例有什么优势吗 public final static MyClass singleton = new MyClass(); 不,实
public static MyClass instance() {
if (singleton == null) {
singleton = new MyClass();
}
return singleton;
}
如果不是因为延迟初始化的效果,这种方法比简单地声明这样的静态实例有什么优势吗
public final static MyClass singleton = new MyClass();
不,实际上是另一种方法,即:
public final static MyClass singleton = new MyClass();
如果您有两个线程同时调用实例方法,您可能会得到一个竞争条件,这可能会更好
Java在实践中是这样说的:
private final static MyClass _instance = new MyClass();
public static MyClass getInstance() {
return _instance;
}
private MyClass() {}
更新自从@jon skeet提到它之后,Joshua Block的《有效Java》一书中对单例进行了非常好的讨论。他指出的一件事是,如果您希望您的单例是可序列化的,那么您不能仅仅实现可序列化。您还需要重写readResolve方法。使用上述方法可以简化此过程:
private Object readResolve() throws ObjectStreamException {
return _instance;
}
更新2:查看关于@mardavi:链接的单例的精彩讨论,除了延迟初始化之外,这两种方法之间的主要区别在于前者不是线程安全的。如果可以的话就避免它。它也不起作用,因为它是一个实例方法…@JonSkeet typo-fixed,感谢您注意到,显式延迟初始化通常都没有好处,因为Java内置的类延迟加载在典型场景中会在您调用
instance()
方法的同时发生。仅当您想将单例初始化与类初始化分离/延迟时才有用。或者,按照有效Java中的建议,使用带有单个值的枚举。就个人而言,我喜欢@mardavi,我已经忘记了这一点。我以前也一直用这个。这种模式的优点是,singleton是懒惰的,对吗?是的,它“尽可能地懒惰”。另外,它不需要特殊的语言结构,这有时可能很重要(至少,我发现没有特殊的单词更容易阅读代码-请原谅通用术语word)