延迟加载的单例 - 静态字段调用会导致实例化

lazy loaded Singleton - will a static field call cause instantiation

根据定义,我有以下你可能称之为延迟加载的单例:

public class MySingleton {

    public static String myTrigger="a trigger";

    private MySingleton(){
    }

    private static enum LazyLoad {
        IMDB_LOOKUP_INSTANCE;
        private static final IMDB_LOOKUP = new MySingleton();
    }

    public static MySingleton getInstance() {
        return LazyLoad.IMDB_LOOKUP_INSTANCE.IMDB_LOOKUP;
    }
}

当我这样打电话时会发生什么:

String someString = MySingleton.myTrigger;

单例不会被实例化吗?

在您调用 MySigleton.getInstance() 之前,您的单例不会被实例化。

您的枚举有问题。所以,我修改了它,下面的代码可以工作并初始化 MySingleton.

public class MySingleton {

public static String myTrigger="a trigger";

private MySingleton(){
    System.out.println("Initialized");
}

private static enum LazyLoad {

    IMDB_LOOKUP_INSTANCE(new MySingleton());

    MySingleton value;

    LazyLoad(MySingleton value){
        this.value = value;
    }

    private MySingleton getValue(){
        return this.value;
    }

}

public static MySingleton getInstance() {
    return LazyLoad.IMDB_LOOKUP_INSTANCE.getValue();
}
}

Class 在您调用 MySingleton.myTrigger 时加载。但是,如果您希望 MySingleton 在 class 加载时进行初始化,请将 MySingleton.getInstance() 放入静态块中。

经过测试(通过在构造函数中放置打印语句),我发现 -

在上面的代码中,直到调用 MySingleton.getInstance()

才会发生实例化

但是,如果您将静态 MySingleton 对象作为 class 的直接 属性,而不是放在枚举中,它将在调用 MySingleton.myTrigger 时实例化,这是因为加载 class 时会实例化所有静态字段。

但在枚举的情况下,枚举不是 class 的静态 属性,它仅在访问时加载。

我也测试过类似的东西 -

class MySingleton {

public static String myTrigger="a trigger";

    private MySingleton(){
        System.out.println("Printing");
    }

    public static enum LazyLoad {
        IMDB_LOOKUP_INSTANCE;
        public static final String Hello = "Hello";
        private static final MySingleton IMDB_LOOKUP = new MySingleton();
    }

    public static MySingleton getInstance() {
        return LazyLoad.IMDB_LOOKUP_INSTANCE.IMDB_LOOKUP;
    }
}

在上面,对 MySingleton.LazyLoad.IMDB_LOOKUP_INSTANCE.Hello 的调用也会导致 MySingleton 对象的实例化。