了解枚举的静态成员初始化

时间:2015-07-03 11:24:20

标签: java constructor enums

Bloch的Effective Java说:

  

不允许枚举构造函数访问枚举的静态字段,   除了编译时常量字段。这种限制是必要的   因为时尚未初始化这些静态字段   构建器运行

对我而言,目前尚不清楚,因为这是JLS所说的:

JLS 8.7

  

当类 时,将在类中声明的静态初始值设定项执行   的初始化

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

1 个答案:

答案 0 :(得分:4)

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

换句话说,你说:

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

“初始化”打印两次,一次创建FOO,一次创建BAR

JLS也对枚举说了这个:

  

从构造函数,实例初始值设定项或枚举类型的实例变量初始化表达式引用枚举类型的static字段是编译时错误,除非该字段是常量变量(§4.12。 4)。