通过enum方式的Singleton是否被延迟初始化? [英] Singleton via enum way is lazy initialized?

查看:138
本文介绍了通过enum方式的Singleton是否被延迟初始化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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 初始化 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆