当前位置: 首页 > 知识库问答 >
问题:

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

施茂
2023-03-14

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

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

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

他并不懒惰(那么渴望)。

但是我不明白为什么,Singleton()constructor只在Singleton类初始化时被调用。我知道几个可能触发类初始化的原因:

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

因此,在这里,我们的对象将仅在使用静态方法getInstance()(我猜它仍然是惰性初始化)和反射(但反射可能会破坏许多单例变量,除了enum)。

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

共有3个答案

段干开宇
2023-03-14

在我看来,Lazy的目标是控制何时创建Singleton实例。在这个例子中,没有控件,因为有一个类变量(静态成员,在类初始化时初始化,而不是在调用getInstance()方法时初始化)。

这样,就无法控制何时创建单例。

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

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

顾磊
2023-03-14

它不是懒惰的,因为单例对象是在类加载后创建的。
懒惰的单例对象会在第一次使用时创建对象。

夹谷茂
2023-03-14

基本上这是懒惰程度的问题。它是懒惰的,因为它在初始化类之前不会构造单例,但它渴望在某些情况下使用类而不初始化单例本身。

例如:

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()将实例化singleton,即使我们不希望它。。。所以它并不像它可能的那么懒惰。

您可以使用嵌套类型绕过此问题:

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。仅使用getInstance方法初始化Holder。它是懒惰的,线程安全,没有锁定。

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

 类似资料:
  • 问题内容: 我读了很多关于Singleton的文章,其中大多数作者都说Java中Singleton的这种变体: 不是LAZY ( 然后 是 EAGER )。 但是我不明白为什么,构造函数只会在类初始化时被调用。我知道几个可以触发类初始化的原因: 与构造函数一起使用(但在这种情况下,构造函数是私有的)。 访问或设置静态字段(此处为私有)。 使用静态方法。 带有反射:。 因此,这里我们的对象将仅在使用

  • 我有模型类别。它可能有父类别和子类别列表。我写这个问题是因为找不到实体和自己相关的情况。 我试图这样实现它: 我保存实体,如: 我希望看到这样的情况: 但是在子模型中,我有递归循环。如何防止它? 是的,我也使用了@JsonIgnore。但是我不确定这是不是一个好的做法。但是如果我有一个案例,当我需要一个类别时,我真的需要将它发送给父母的UI。@JsonIgnore可以产生这个吗?

  • 问题内容: 我正在使用Eclipse在Android中开发应用程序。我编写了以下代码,并在测试中无法访问第一个和第三个“ if ”块。为什么? 当我在数字前添加零时,等于运算符将返回false。 问题答案: 是一个八进制数字(前导0),而是一个十进制数字。 所以0123实际上等于83

  • 我试着把我的头绕到相对较新的img属性“加载”上。 我知道,如果img具有load=“lazy”属性,那么它会告诉支持该属性的浏览器,在接近视口时可以加载该属性。 那么为什么不总是设置loading=“lazy”?那些立即出现在屏幕上的图像无论如何都会被渲染,因为它们已经在视口中了。因此,在这种情况下,基本上忽略了load=“lazy”。 在这个演示https://mathiasbynens.be

  • 问题内容: 我知道整数在Java中是不可变的。但是为什么要这样设计呢? 我找不到强制Integer不可变的用例。是否有类似String的技术原因? 字符串在网络连接,数据库URL等中用作参数。如果它是可变的,则很容易遭到破坏。 支持StringPool功能。 支持使用字符串作为参数的类加载机制。字符串可变会导致加载错误的类。 我知道有些包装很易变。 更新: 从对话中,并没有普遍的理由要求整数是不可