Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如果不是惰性初始化,使用方法而不是静态类成员构建单例是否有任何优势?_Java - Fatal编程技术网

Java 如果不是惰性初始化,使用方法而不是静态类成员构建单例是否有任何优势?

Java 如果不是惰性初始化,使用方法而不是静态类成员构建单例是否有任何优势?,java,Java,我经常看到singleton是这样构建的: public static MyClass instance() { if (singleton == null) { singleton = new MyClass(); } return singleton; } 如果不是因为延迟初始化的效果,这种方法比简单地声明这样的静态实例有什么优势吗 public final static MyClass singleton = new MyClass(); 不,实

我经常看到singleton是这样构建的:

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)