【发布时间】:2015-09-21 05:29:56
【问题描述】:
Bloch 的 Effective Java 是这么说的:
枚举构造函数不允许访问枚举的静态字段, 除了编译时常量字段。这个限制是必要的 因为这些静态字段在时还没有被初始化 构造函数运行。
对我来说,不清楚,因为这就是 JLS 所说的:
类中声明的静态初始化器在类是时执行 已初始化
因此,所有静态成员都在任何构造函数的调用开始之前被初始化。我错过了什么?
【问题讨论】:
标签: java constructor enums
Bloch 的 Effective Java 是这么说的:
枚举构造函数不允许访问枚举的静态字段, 除了编译时常量字段。这个限制是必要的 因为这些静态字段在时还没有被初始化 构造函数运行。
对我来说,不清楚,因为这就是 JLS 所说的:
类中声明的静态初始化器在类是时执行 已初始化
因此,所有静态成员都在任何构造函数的调用开始之前被初始化。我错过了什么?
【问题讨论】:
标签: java constructor enums
枚举的常量本身是通过调用构造函数来初始化的。这意味着构造函数无法访问该常量,因为它当时尚未创建。
换句话说,假设你有:
enum MyEnum {
FOO, BAR;
private MyEnum() {
// Illegal
// FOO already calls this constructor
System.out.println(FOO);
}
}
FOO 和 BAR 等价于:
public static final MyEnum foo;
public static final MyEnum bar;
当 JVM 加载枚举类时,通过调用枚举私有构造函数创建 FOO 和 BAR,类似于:
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 节) .
【讨论】: