Создание нового экземпляра класса внутри конструктора enum, когда enum находится в классе - PullRequest
0 голосов
/ 14 сентября 2018

Изначально я думал, что у меня будут проблемы с курицей и яйцом, но изучение этого в модульном тесте не показывает никаких проблем. Я хочу понять, что здесь происходит. Я бы подумал, что, поскольку перечисления являются статическими и окончательными, конструктор MyEnum будет работать при загрузке JVM MyClass. Однако в моем тесте он выводит «getValue» перед «конструктором MyEnum».

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();
    }
}

1 Ответ

0 голосов
/ 14 сентября 2018

Тот факт, что класс / интерфейс / перечисление / аннотация вложен в другой класс, не влияет на то, когда произойдет его инициализация.

Правила инициализации применяются независимо.Они определены в 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, которая снова печатает в стандартный вывод.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...