public enum MyEnum1 {
FOO(BAR), BAR(FOO);
private MyEnum1 other;
private MyEnum1(MyEnum1 other) {
this.other = other;
}
public MyEnum1 getOther() {
return other;
}
}
MyEnum1
generates the error Cannot reference a field before it is defined
, which is quite understandable, since declaration order matters here. But why does the following compile?
public enum MyEnum2 {
FOO { public MyEnum2 getOther() { return BAR; } },
BAR { public MyEnum2 getOther() { return FOO; } };
public abstract MyEnum2 getOther();
}
FOO
refers to BAR
before BAR
is defined, am I wrong?
The important JLS parts are this and this
A class or interface type T will be initialized immediately before the first occurrence of any one of the following:
T is a class and an instance of T is created.
T is a class and a static method declared by T is invoked.
A static field declared by T is assigned.
A static field declared by T is used and the field is not a constant variable (§4.12.4).
T is a top level class (§7.6), and an assert statement (§14.10) lexically nested within T (§8.1.3) is executed.
And
The optional class body of an enum constant implicitly defines an anonymous class declaration (§15.9.5) that extends the immediately enclosing enum type.
So with
FOO { public MyEnum2 getOther() { return BAR; } },
BAR { public MyEnum2 getOther() { return FOO; } };
you are creating two anonymous classes extending MyEnum2
.
When BAR
is eventually reference either when you call Foo.getOther()
or some other piece of code does MyEnum2.Bar
, the type will be initialized.
you are creating enum constant with reference to yet undeclared constant in first case. In second case it does not matter because of compilation order, enumeration constants are compiled before enumeration body. I would say this is the reason. If it was not true, compilation would fail earlier because abstract method declaration is defined after the non-abstract method declaration in body of each enum constant.
Good reference - http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.9
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With