通过枚举方式的单例是否被延迟初始化?

这是一个非常广泛的枚举单例代码:

public enum enumClazz{

INSTANCE

enumClazz(){

//do something

}

}

一堆地方说这是一个懒惰的初始化。但我很困惑我“读的第7章后,里面的Java虚拟机

” -一个类型的生命周期:

Java虚拟机规范在类和接口加载和链接的时间上为实现提供了灵活性,但严格定义了初始化的时间。所有实现都必须在首次使用时初始化每个类或接口。以下六种情况可作为有效使用:

  • 将创建一个类的新实例(以字节码表示,一条新指令的执行。或者,通过隐式创建,反射,克隆或反序列化。)
  • 由类声明的静态方法的调用(以字节码表示,invokestatic指令的执行)

    *

  • Java API中某些反射方法的调用,例如Class类中的方法或java.lang.reflect包中的类中的方法
  • 类的子类的初始化(类的初始化需要其超类的事先初始化。)
  • Java虚拟机启动时,将类指定为初始类(使用main()<方法)

第三点用粗体表示,如果该字段为static final,则该字段的初始化在编译时进行。同样,INSTANCEin

enumClazz隐式等于public static final并遵守第三点。

如果我的理解是错误的,有人可以纠正我吗?

回答:

enum实例字段 不是

“由编译时常量表达式初始化”。不能这样,因为对于编译时常量表达式,只有String和基本类型是可能的类型。

这意味着该类将在INSTANCE首次访问时进行初始化(这正是所需的效果)。

上面的粗体文本存在一个例外,因为这些常量(static final使用编译时常量表达式初始化的字段)将在编译期间有效地内联:

class A {

public static final String FOO = "foo";

static {

System.out.println("initializing A");

}

}

class B {

public static void main(String[] args) {

System.out.println(A.FOO);

}

}

B在此示例中,执行类将 初始化A(并且 不会显示

“正在初始化A”)。并且,如果您查看为之生成的字节码,B您会看到一个字符串文字,其值为“ foo”,并且 没有 对该类的引用A

以上是 通过枚举方式的单例是否被延迟初始化? 的全部内容, 来源链接: utcz.com/qa/405747.html

回到顶部