从初始化程序中非法引用静态字段

问题描述 投票:0回答:4

我是java中枚举的新手,我很困惑为什么这段代码编译得很好

enum Scale5 {
GOOD(), BETTER(), BEST();
static  Scale5 s=GOOD;
}

但是这段代码失败了:

enum Scale5 {
GOOD(), BETTER(), BEST();
Scale5 s=GOOD;
}

我收到错误:从初始化程序非法引用静态字段。 我不明白原因。我对枚举比较缺乏经验,所以请帮我把它转下来。非常感谢!

这里提出的问题不能在初始化器中引用静态枚举字段?与我所问的完全相反。在我的例子中,将 s 声明为 static 可以很好地编译代码。

java class oop enums static
4个回答
5
投票

想像这样的枚举:

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;
}

5
投票

来自Java语言规范

引用枚举类型的静态字段是一个编译时错误 这不是构造函数、实例中的常量变量(第 4.12.4 节) 初始化块,或实例变量初始化表达式 那种类型。


2
投票

非常简单。第一种情况有效,因为编译器定义了所有枚举常量,然后初始化静态变量。因此,此时 GOOD 已经存在,一切都很好。

在第二种情况下,所有枚举常量都存在该变量,因此,当您创建 GOOD (或 BETTER 或 BEST)时,GOOD 必须已被定义和绑定。这当然是非法的。


0
投票

考虑以下示例:

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

 已使用正确的值初始化时,
将被执行。

© www.soinside.com 2019 - 2024. All rights reserved.