我看了很多关于Singleton的文章,其中大部分作者都说Java中Singleton的这种变体:
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
是不懒惰(然后是 EAGER)。
但我不明白为什么,Singleton()
构造函数只会在 Singleton
类初始化时被调用。我知道几个可以触发类初始化的原因:
- 将
new
与构造函数一起使用(但在这种情况下,构造函数是私有(private)的)。 - 访问或设置静态字段(此处为私有(private))。
- 使用静态方法。
- 使用反射:
Class.forName("Singleton")
。
所以这里我们的对象将仅在使用静态方法getInstance()
(我猜它仍然是LAZY初始化)和反射(但反射会破坏一个很多单例变体,除了 enum
可能)。
也许我看不到明显的东西,请解释一下,我哪里错了?
最佳答案
基本上这是一个懒惰程度的问题。它是惰性的,因为它在初始化类之前不会构造单例,但它是急切的,因为可能您希望在不初始化单例本身的情况下使用该类。
例如:
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
方法,在这种情况下它们是等价的(假设您不使用反射来初始化例如,某种类型)。
关于java - 为什么 private static field = new Singleton 在 Java 中不懒惰?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24487095/