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

时间:2014-06-30 09:36:50

标签: java singleton

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

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

    private Singleton() {}
    public static Singleton getInstance() {
        return instance;
    }
}

NOT LAZY EAGER then )。

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

  1. new与构造函数一起使用(但在本例中构造函数是私有的)。
  2. 访问或设置静态字段(此处为私有字段)。
  3. 使用静态方法。
  4. 反思:Class.forName("Singleton")
  5. 所以这里我们的对象只会在使用静态方法getInstance()时创建(它仍然是 LAZY 初始化我猜)和反射(但反射可能会破坏很多Singleton变体,除了enum之外可能。)

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

3 个答案:

答案 0 :(得分: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!");
    }
}

调用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();
    }
}

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

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

答案 1 :(得分:5)

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

答案 2 :(得分:0)

在我看来,成为惰性的目标是控制创建Singleton实例的时间。 在此示例中,没有控制,因为存在一个类变量(在初始化该类时而不是在调用getInstance()方法时初始化的静态成员)。

这样,就无法控制创建Singleton的时间。

但是,如果在getInstance内部初始化变量,则可以控制何时创建Singleton。

正如您所说,有很多单例的例子。如果需要,我总是尝试去枚举。 您可以在此处找到示例:https://connected2know.com/programming/java-singleton-pattern/