为什么私有静态字段=新的Singleton在Java中不是懒惰的?

mar*_*all 6 java singleton

我阅读了很多关于Singleton的文章,其中大多数作者都说Java中的Singleton变种:

public class Singleton {
    private static Singleton instance = new Singleton();

    private Singleton() {}
    public static Singleton getInstance() {
        return instance;
    }
}
Run Code Online (Sandbox Code Playgroud)

不懒惰(EAGER然后).

但我无法理解为什么,Singleton()constuctor只会在Singleton类初始化时调用.我知道几个可以触发类初始化的原因:

  1. 使用new构造函数(但在这种情况下构造函数是私有的).
  2. 访问或设置静态字段(此处为私有).
  3. 使用静态方法.
  4. 随着反思:Class.forName("Singleton").

所以这里我们的对象只会在使用静态方法时创建getInstance()(它仍然是LAZY初始化)和反射(但反射可能会破坏很多Singleton变体,除了enum可能).

也许我看不到明显的东西,请解释一下,我哪里错了?

Jon*_*eet 13

基本上这是一个懒惰程度的问题.它是懒惰的,因为它不会在类初始化之前构造单例,但是它很渴望可能存在你想要使用类而不初始化单例本身的情况.

例如:

public final class Singleton {
    private static final Singleton instance = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() {
        return instance;
    }

    public static void sayHello() {
        System.out.println("Hello!");
    }
}
Run Code Online (Sandbox Code Playgroud)

调用Singleton.sayHello()将实例化单例,即使我们不希望它...所以它不是那么懒惰.

你可以使用嵌套类型来解决这个问题:

public final class Singleton {
    private Singleton() {}

    public static Singleton getInstance() {
        return Holder.instance;
    }

    public static void sayHello() {
        System.out.println("Hello!");
    }

    private static class Holder {
        private static final Singleton instance = new Singleton();
    }
}
Run Code Online (Sandbox Code Playgroud)

现在Singleton.Holder只使用该getInstance方法初始化.它是懒惰和线程安全的,没有锁定.

根据我的经验,通常单例类的唯一静态方法是getInstance方法,在这种情况下它们是等效的(例如,假设您不使用反射以某种方式初始化类型).

  • @marshall:嗯,使用其他静态方法时,"在调用其他方法时会很渴望".例如,在"当应用程序启动时"时,就像渴望一样.就个人而言,我会尽量避免使用单身人士,大多数情况下:) (2认同)

Ale*_*ien 5

它不是懒惰的,因为一旦加载了类就会创建singeton对象.
懒惰的Singleton会在首次使用时创建对象.

  • 但正如我在问题中所说,类只会加载到getInstance()方法.你没有读过或者不同意我的看法?告诉我为什么请,我无法理解. (2认同)
  • 恕我不能赞同.Singleton theSingleton不会加载该类. (2认同)