我是java中枚举的新手,我很困惑为什么这段代码编译得很好
enum Scale5 {
GOOD(), BETTER(), BEST();
static Scale5 s=GOOD;
}
但是这段代码失败了:
enum Scale5 {
GOOD(), BETTER(), BEST();
Scale5 s=GOOD;
}
我收到错误:从初始化程序非法引用静态字段。 我不明白原因。我对枚举比较缺乏经验,所以请帮我把它转下来。非常感谢!
这里提出的问题不能在初始化器中引用静态枚举字段?与我所问的完全相反。在我的例子中,将 s 声明为 static 可以很好地编译代码。
想像这样的枚举:
public final class Scale5
{
public static final Scale5 GOOD = new Scale5();
public static final Scale5 BETTER = new Scale5();
public static final Scale5 BEST = new Scale5();
static Scale5 s = GOOD;//works because GOOD is initialized first;
Scale5 ss = GOOD;//doesn't work because in order to initialize GOOD,
//ss must be assigned an object that is not yet initialized;
}
来自Java语言规范:
引用枚举类型的静态字段是一个编译时错误 这不是构造函数、实例中的常量变量(第 4.12.4 节) 初始化块,或实例变量初始化表达式 那种类型。
非常简单。第一种情况有效,因为编译器定义了所有枚举常量,然后初始化静态变量。因此,此时 GOOD 已经存在,一切都很好。
在第二种情况下,所有枚举常量都存在该变量,因此,当您创建 GOOD (或 BETTER 或 BEST)时,GOOD 必须已被定义和绑定。这当然是非法的。
考虑以下示例:
class X {
public static final X GOOD = new X();
X y = GOOD;
static X z = GOOD;
public static void main(String[] args) {
System.out.println(GOOD);
System.out.println(GOOD.y);
System.out.println(X.z);
}
}
输出:
X@1db9742
null
X@1db9742
如您所见,
GOOD.y
的值是null
。那是因为在初始化值时
public static final X GOOD = new X();
当您调用
new X()
时,您将使用 GOOD
的当前值,即 null
,直到 new X()
完成。虽然在普通类中这种行为是允许的,但对于枚举来说是被禁止的,可能是因为它经常被误解。
对于静态字段,问题就消失了,因为它们是按照声明的顺序执行的,所以
static X z = GOOD;
当我们确定 GOOD
已使用正确的值初始化时,将被执行。