java - 为什么 private static field = new Singleton 在 Java 中不懒惰?

标签 java singleton

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

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

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

不懒惰(然后是 EAGER)。

但我不明白为什么,Singleton() 构造函数只会在 Singleton 类初始化时被调用。我知道几个可以触发类初始化的原因:

  1. new 与构造函数一起使用(但在这种情况下,构造函数是私有(private)的)。
  2. 访问或设置静态字段(此处为私有(private))。
  3. 使用静态方法。
  4. 使用反射: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/

相关文章:

java - pom 编辑器中的 Eclipse Maven 错误 : org. apache.maven.plugin.jar.JarMojo 错误

java - 关于单例设计模式

ruby - 为什么 Ruby 模块包含排除了模块的单例类?

android - Facebook session 单例使用

java - 用适当的java代码替换表情符号

java - 未命名的json数组到java

java - 激活失败 - 适用于 Netbeans 的诺基亚 SDK

java - "current directory"中的 Spring Boot 外部属性文件被忽略

java - 如何在 Java 代码中使用 scala.None

c# - 自动属性初始化器单例实现