This code won't compile because there is an illegal reference to a static field.
public enum Foo {
A,
B;
private Foo[] foos = new Foo[] { Foo.A };
}
Shouldn't you be able to access static fields from a non-static field initializer? For example:
public class Foo {
static int A;
private int[] foos = new int[] { Foo.A };
}
This compiles fine.
Note, making foos
static in the first example compiles.
The enum class body can include methods and other fields. The compiler automatically adds some special methods when it creates an enum. For example, they have a static values method that returns an array containing all of the values of the enum in the order they are declared.
Yes, enums are effectively static.
Enum fields are treated like fields on any other type. Again, because enum values are constants, fields should be final variables, since they will not change.
The types of all fields of the enum are deeply immutable. For example, use ImmutableList and ImmutableSet instead of List and Set . Types are considered immutable if they are primitives, in a set of types that are built in to Error Prone (e.g. java.
Check out Java Language Specification, Third Edition, Section 8.9 at http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.9
It is a compile-time error to reference a static field of an enum type that is not a compile-time constant (§15.28) from constructors, instance initializer blocks, or instance variable initializer expressions of that type. It is a compile-time error for the constructors, instance initializer blocks, or instance variable initializer expressions of an enum constant e to refer to itself or to an enum constant of the same type that is declared to the right of e.
Discussion
Without this rule, apparently reasonable code would fail at run time due to the initialization circularity inherent in enum types. (A circularity exists in any class with a "self-typed" static field.) Here is an example of the sort of code that would fail:
enum Color {
RED, GREEN, BLUE;
static final Map<String,Color> colorMap =
new HashMap<String,Color>();
Color() {
colorMap.put(toString(), this);
}
}
Static initialization of this enum type would throw a NullPointerException because the static variable colorMap is uninitialized when the constructors for the enum constants run. The restriction above ensures that such code won't compile.
Written out in a roughly equivalent, simpler way, closer to the byte code, we see:
public final class Foo {
public static final Foo A = new Foo();
public static final Foo B = new Foo();
private Foo[] foos;
private Foo() {
this.foos = new Foo[] { Foo.A };
}
}
You can see that to initialise A
we are calling the constructor, which reads A
. Obviously, whilst still in the constructor A
will not have been initialised.
(As it turns out, this simpler code does compile. It just doesn't do what you might expect.)
You probably want Foo.values()
instead of the foos
instance variable.
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