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

是否已初始化此singleton lazy?

宋稳
2023-03-14

我有这样的代码:

class Singleton {

    private static final Singleton INSTANCE = new Singleton();

    private Singleton() {
        System.out.println("Singleton constructed.");
    }

    public static Singleton getInstance() {
        return INSTANCE;
    }

}

当我们没有任何其他getInstance的静态方法时,是否初始化了此单例惰性?据我所知,类只在某些情况下初始化,比如:

  1. 类的实例是使用new()关键字或使用类的反射创建的。forName(),它可能在Java中引发ClassNotFoundException

(Surce:http://javarevisited.blogspot.com/2012/07/when-class-loading-initialization-java-example.html#ixzz4IjIe2Rf5)

因此,当唯一的静态方法是getInstance并且构造函数是私有的时,除了使用getInstance方法(除了反射)之外,没有任何其他方式初始化Singleton类的可能性。所以只有在我们需要的时候才会创建对象,所以这是一个懒惰的初始化,对吗?或者我错过了什么?

共有3个答案

易招
2023-03-14

编辑:我错了。类不是通过引用来加载的,如下所示:

System.out.println(Singleton.class); 

创建实例、引用静态成员或以编程方式加载时,类加载器会立即加载类:

Class<?> clazz = Class.forName("Singleton"); // fully qualified classname

上面的语句导致类被加载,所有静态成员和块都将按照类中出现的顺序进行处理。在示例类中,这将导致初始化实例变量(并将消息打印到System.out)。这证明您的方法不能保证延迟加载。

实现延迟加载单例的更好方法是使用单例持有人模式:

class Singleton {

    private static class Holder {
        private static final Singleton INSTANCE = new Singleton();
    }

    private Singleton() {
        // hide constructor
    }

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

}
翟修永
2023-03-14

它是立即初始化的,所以不,不是。通常,延迟初始化意味着您在尝试实际检索时对其进行初始化,但字段尚未初始化。

懒惰初始化与类初始化无关——它与包含在其中的字段有关。在您的情况下,一旦类被加载,该字段将立即初始化。

您的示例适合使用惰性初始化:

class Singleton {
    private static Singleton INSTANCE;

    private Singleton() {
        System.out.println("Singleton constructed.");
    }

    public static Singleton getInstance() {
        if(INSTANCE == null) {
            INSTANCE = new Singleton();
        }
        return INSTANCE;
    }
}

这将仅在实际请求时构造单例,而不仅仅是在内存中加载singleton类时。在您的情况下,如果它加载到内存中,那么它的静态字段将被初始化(包括您的单例字段)。

范京
2023-03-14

您提到了静态方法和私有构造函数。添加另一个静态字段,类似于:

static int NUMBER = 13;

在你的单身班。在其他类别的主要方法中:

System.out.println(Singleton.NUMBER);

然后,您将看到您的单例不是惰性初始化的。

但是,当您的字段是静态最终字段时:

static final int NUMBER = 13;

单例是惰性初始化的。

更重要的是,当您在Singleton类中添加静态和非静态初始化块时:

{
    System.out.println("non-static");
}

static {
    System.out.println("static");
}

顺序是:非静态,私有构造函数,然后是静态的,因为您正在将一个对象作为静态字段的值进行设置。所以,这是非常棘手的:)

总之,在某些情况下,您的单例可能被认为是延迟初始化的,但通常情况下并非如此。

 类似资料:
  • 问题内容: 如果我在代码中使用如下语句 它将数组初始化为特定的东西吗?(例如0)我似乎记得此文件记录在某处,但我不确定要搜索什么。 问题答案: JLS说,在15.10数组创建表达式中 […]创建具有指定长度的一维数组,并将数组的每个组件初始化为其默认值 在4.12.5变量的初始值处表示: 对于type ,默认值为零,即。

  • 问题内容: 我需要使用类似于php的isset函数的东西。我知道php和java截然不同,但是php是我先前类似编程知识的唯一基础。是否有某种方法可以返回一个布尔值,用于确定实例变量是否已初始化。例如… 到目前为止,我遇到了这个问题,当我的程序试图隐藏或删除尚未构造的对象时,出现运行时错误。 问题答案: 假设您对是否已为变量 明确赋值 感兴趣,答案是“不是真的”。但绝对的字段(实例变量或类变量)尚

  • 我想知道是否有一种方法可以检查变量是否已经初始化。例如:

  • 我想知道是否有办法检查变量是否已初始化。例如:

  • 问题内容: 哪种方法检查变量是否已初始化是更好/正确的方法?(假设变量可以容纳任何内容(字符串,整数,对象,函数等)) 要么 要么 问题答案: 该运营商将检查变量真的不确定。 该运营商,不同于其他运营商,不会抛出 的ReferenceError 与未声明的变量使用时例外。 但是,请注意将返回。我们必须小心避免将变量初始化为的错误。为了安全起见,我们可以改用以下方法:

  • 问题内容: 当我测试新插件时,不断抛出异常:java.lang.IllegalArgumentException:插件已初始化!请帮忙!这是代码: 我知道您只应该为每个插件声明一个JavaPlugin类,我认为我正在这样做。但它一直在说: 我真的需要测试此插件,看看它是否有效,任何帮助将不胜感激!谢谢! 问题答案: stacktrace清楚地指出了问题出在哪里。什么是堆栈跟踪,如何使用它来调试应用