通过enum方式的Singleton是否被延迟初始化? [英] Singleton via enum way is lazy initialized?
问题描述
这是一个非常广泛的枚举单例代码:
This is a very wide-spread enum singleton code:
public enum enumClazz{
INSTANCE
enumClazz(){
//do something
}
}
和一堆地方说这是一个懒惰的初始化。但在阅读 Java虚拟机内部第7章后,我感到困惑。 - 类型的生命周期:
and a bunch of places said it is a lazy initialization. But I am confused after I read Chapter 7 of 'Inside the Java Virtual Machine' -- The Lifetime of a Type:
Java虚拟机规范为类和接口加载的时序提供了实现
的灵活性和链接,
但严格定义初始化的时间。所有实现
必须在其第一次活动使用时初始化每个类或接口。六种情况下的
有资格作为有效用途:
The Java virtual machine specification gives implementations flexibility in the timing of class and interface loading and linking, but strictly defines the timing of initialization. All implementations must initialize each class or interface on its first active use. The following six situations qualify as active uses:
- 创建一个新的类实例(在字节码中,执行或者,通过隐式创建,
反射,克隆或反序列化。) - 调用类声明的静态方法(在字节码中,执行一个invokestatic指令)
- 使用或赋值由类或接口声明的静态字段,除了最终的静态字段并由
a编译时初始化常量表达式(在字节码中,执行
getstatic或putstatic指令) - 调用Java API中的某些反射方法,例如类中的方法java.lang.reflect
包中的类或类 - 类的子类的初始化(类的初始化需要事先初始化其超类。)
- 将类指定为初始类(使用main()<方法)当Java虚拟机启动时
- A new instance of a class is created (in bytecodes, the execution of a new instruction. Alternatively, via implicit creation, reflection, cloning, or deserialization.)
- The invocation of a static method declared by a class (in bytecodes, the execution of an invokestatic instruction)
- The use or assignment of a static field declared by a class or interface, except for static fields that are final and initialized by a compile-time constant expression (in bytecodes, the execution of a getstatic or putstatic instruction)
- The invocation of certain reflective methods in the Java API, such as methods in class Class or in classes in the java.lang.reflect package
- The initialization of a subclass of a class (Initialization of a class requires prior initialization of its superclass.)
- The designation of a class as the initial class (with the main()< method) when a Java virtual machine starts up
第三点用粗体风格澄清如果字段是 static final
,字段的初始化发生在编译时。同样, enumClazz
中的 INSTANCE
隐含等于 public static final
并遵守第三点。
The third point with bold style clarify that if the field is static final
, the initialization of the field is happened at compile-time. Likewise, the INSTANCE
in enumClazz
is implicitly equal to public static final
and comply with the third point.
如果我的理解错误,有人可以纠正我吗?
Can someone correct me if my understanding is wrong?
推荐答案
枚举
实例字段不由编译时常量表达式初始化。他们
不能,因为只有字符串
和原始类型是编译时常量表达式的可能类型。
enum
instance fields are not "initialized by a compile-time constant expression". They
can't be, because only String
and primitive types are possible types for a compile-time constant expression.
这意味着当首次访问 INSTANCE
时,该类将被初始化(这正是所需的效果)。
That means that the class will be initialized when INSTANCE
is first accessed (which is exactly the desired effect).
上面的粗体文本中存在异常,因为这些常量( static final
字段使用编译时常量表达式初始化)将在编译期间有效内联:
The exception in the bold text above exists, because those constants (static final
fields initialized with a compile-time constant expression) will effectively be inlined during compilation:
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 在此示例中,code>将不初始化
A
(不会打印初始化A)。如果你查看为 B
生成的字节码,你会看到一个字符串文字,其值为foo而没有引用该类 A
。
Executing class B
in this example will not initialize A
(and will not print "initializing A"). And if you look into the bytecode generated for B
you'll see a string literal with the value "foo" and no reference to the class A
.
这篇关于通过enum方式的Singleton是否被延迟初始化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!