【问题标题】:Understanding enum's static members initialization [duplicate]了解枚举的静态成员初始化[重复]
【发布时间】:2015-09-21 05:29:56
【问题描述】:

Bloch 的 Effective Java 是这么说的:

枚举构造函数不允许访问枚举的静态字段, 除了编译时常量字段。这个限制是必要的 因为这些静态字段在时还没有被初始化 构造函数运行

对我来说,不清楚,因为这就是 JLS 所说的:

JLS 8.7:

类中声明的静态初始化器在类时执行 已初始化

因此,所有静态成员都在任何构造函数的调用开始之前被初始化。我错过了什么?

【问题讨论】:

    标签: java constructor enums


    【解决方案1】:

    枚举的常量本身是通过调用构造函数来初始化的。这意味着构造函数无法访问该常量,因为它当时尚未创建。

    换句话说,假设你有:

    enum MyEnum {
    
       FOO, BAR;
    
       private MyEnum() {
            // Illegal
            // FOO already calls this constructor
            System.out.println(FOO);
       }
    
    }
    

    FOOBAR 等价于:

    public static final MyEnum foo;
    public static final MyEnum bar;
    

    当 JVM 加载枚举类时,通过调用枚举私有构造函数创建 FOOBAR,类似于:

    foo = MyEnum(); // name of enum, the params are not relevant
    bar = MyEnum(); 
    

    因此 Java 不允许您访问构造函数中的该字段,因为它仍在创建中。您可以运行以下命令进行验证:

    enum MyEnum {
        FOO, BAR;
    
        private MyEnum() {
            System.out.println("Initializing");
        }
    }
    
    public static void main(String[] args) {
        System.out.println(MyEnum.FOO);
    }
    

    输出:

    Initializing
    Initializing
    FOO
    

    “Initializing”被打印两次,一次由FOO 创建,另一次由BAR 创建。

    JLS 也提到了枚举:

    从枚举类型的构造函数、实例初始化器或实例变量初始化器表达式引用枚举类型的 static 字段是编译时错误,除非该字段是常量变量(第 4.12.4 节) .

    【讨论】:

    • 规则不太清楚。你不能给出比“标准这么说”更好的解释吗? :)要创建某个类的实例,我们必须首先对其进行初始化。我认为,枚举也不例外,所以当 JVM 开始创建枚举的实例时,枚举已经初始化。所以,静态初始化器已经被执行,这意味着我们可以安全地从构造函数中访问它。
    猜你喜欢
    • 2013-10-29
    • 1970-01-01
    • 2013-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多