似乎我可以*在定义之前引用一个字段*

sp0*_*00m 5 java enums static declaration

public enum MyEnum1 {

    FOO(BAR), BAR(FOO);

    private MyEnum1 other;

    private MyEnum1(MyEnum1 other) {
        this.other = other;
    }

    public MyEnum1 getOther() {
        return other;
    }

}
Run Code Online (Sandbox Code Playgroud)

MyEnum1生成错误Cannot reference a field before it is defined,这是可以理解的,因为声明顺序在这里很重要.但为什么以下编译呢?

public enum MyEnum2 {

    FOO { public MyEnum2 getOther() { return BAR; } },
    BAR { public MyEnum2 getOther() { return FOO; } };

    public abstract MyEnum2 getOther();

}
Run Code Online (Sandbox Code Playgroud)

FOO是指定义BAR之前BAR,我错了吗?

Sot*_*lis 2

JLS 重要的部分是这个这个

\n\n
\n

类或接口类型 T 将在第一次出现以下任一情况之前立即初始化:

\n\n

T 是一个类,并且创建了 T 的实例。

\n\n

T 是一个类,并且调用 T 声明的静态方法。

\n\n

由 T 声明的静态字段被赋值。

\n\n

使用 T 声明的静态字段,并且该字段不是常量\n 变量 (\xc2\xa74.12.4)。

\n\n

T 是顶级类 (\xc2\xa77.6),并且执行词法嵌套在 T (\xc2\xa78.1.3) 内的断言语句 (\xc2\xa714.10)\n。

\n
\n\n

\n\n
\n

枚举常量的可选类主体隐式定义了一个匿名类声明 (\xc2\xa715.9.5),该声明扩展了直接\n 封闭的枚举类型。

\n
\n\n

所以与

\n\n
FOO { public MyEnum2 getOther() { return BAR; } }, \nBAR { public MyEnum2 getOther() { return FOO; } };\n
Run Code Online (Sandbox Code Playgroud)\n\n

您正在创建两个扩展的匿名类MyEnum2

\n\n

当您调用或其他代码片段BAR最终引用时,类型将被初始化。Foo.getOther()MyEnum2.Bar

\n