Reputation: 120188
Initially I thought I would have a chicken and egg problem here, but exploring this in a unit test doesn't indicate any problems. I want to understand what is going on here. I would have thought that since enums are static and final the MyEnum
constructor would run when the JVM loads MyClass
. However in my test it prints "getValue" before "MyEnum constructor".
MyClass {
private enum MyEnum {
VALUE;
MyEnum() {
System.out.println("MyEnum constructor");
MyClass clazz = new MyClass();
}
}
public MyEnum getValue() {
System.out.println("getValue");
return MyEnum.VALUE;
}
}
public class MyClassTest {
@Test
public void testStuff() {
MyClass clazz = new MyClass();
clazz.getValue();
}
}
Upvotes: 1
Views: 633
Reputation: 3531
The fact that a class/interface/enum/annotation is nested within another class does not affect when its initialization will occur.
The rules for initialization apply regardless. They are defined in the JLS here.
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.
- 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).
The JLS also says the following about enum
types
An enum declaration specifies a new enum type, a special kind of class type.
And about its members, it says
For each enum constant c declared in the body of the declaration of
E
,E
has an implicitly declaredpublic static final
field of typeE
that has the same name asc
. The field has a variable initializer which instantiatesE
and passes any arguments ofc
to the constructor chosen forE
. The field has the same annotations asc
(if any).
Put all this together and you get an explanation for the behavior you see.
Your code instantiates MyClass
, then invokes its getValue()
method. getValue()
prints something to standard out and then tries to access a static field declared by MyEnum
. This triggers initialization of the enum type, which initializes the public static static VALUE
field, which invokes the corresponding MyEnum
construct that again prints to standard out.
Upvotes: 1