Тот факт, что класс / интерфейс / перечисление / аннотация вложен в другой класс, не влияет на то, когда произойдет его инициализация.
Правила инициализации применяются независимо.Они определены в JLS здесь .
Класс T или интерфейсный тип T будут инициализированы непосредственно перед первым появлением любого из следующего:
- T является классом, и создается экземпляр T.
- Вызывается статический метод, объявленный T.
- Назначается статическое поле, объявленное T.
- Используется статическое поле, объявленное T, и поле не является константной переменной (§4.12.4).
JLS также говорит следующее о enum
types
Объявление enum определяет новый тип enum, специальный тип типа класса .
And о своих членах , он говорит
Для каждой константы c, объявленной в теле объявления E
, E
имеет неявно объявленное поле public static final
введите E
с тем же именем, что и c
.Поле имеет инициализатор переменной, который создает экземпляр E
и передает любые аргументы c
конструктору, выбранному для E
.Поле имеет те же аннотации, что и c
(если есть).
Соберите все это вместе, и вы получите объяснение поведения, которое вы видите.
Ваш код создает MyClass
, затем вызывает его getValue()
метод.getValue()
распечатывает что-то в стандартный формат и затем пытается получить доступ к статическому полю, объявленному MyEnum
.Это инициирует инициализацию типа enum, который инициализирует поле public static static VALUE
, которое вызывает соответствующую конструкцию MyEnum
, которая снова печатает в стандартный вывод.