Инициализация двойной двойки Java работает всегда?

Я знаю, что этот код:

Set<String> set = new HashSet<String>() {{
  add("test1");
  add("test2");
}};

действительно:

Set<String> set = new HashSet<String>() {
  {//initializer
    add("test1");
    add("test2");
  }
};

Блок инициализации выполняется до блока конструктора. В приведенном выше примере add ( "test1" ) вызывается перед выполнением конструктора. Конструктор может инициализировать многие поля экземпляра, чтобы этот класс работал. Мне интересно, зачем вызывать .add() до того, как будет работать конструктор? Есть ли какой-либо случай, который может вызвать проблему?

Ответы

Ответ 1

Есть информация, которую вы оставили, что объясняет это.

Прежде всего, давайте рассмотрим шаги с 3 по 5 процедуры инициализации раздел 15.9.1.)

Поскольку вы не объявили конструктор, используется конструктор по умолчанию. Но до этого конструктор суперкласса HashSet завершился.

Итак, в итоге конструктор HashSet завершается до запуска блока инициализации.

Ответ 2

Это предположение неверно:

Блок инициализации выполняется перед блоком конструктора.

Поскольку в этом конкретном случае блок инициализатора является частью блока конструктора.

docs ясно, что

Компилятор Java копирует блоки инициализации в каждый конструктор. Поэтому этот подход может использоваться для совместного использования блока кода между несколькими конструкторами.

Я думаю, вы запутались со статическими инициализаторами.

Ответ 3

Инициализаторы экземпляра выполняются сразу после создания объекта. Вы в основном создаете встроенное расширение HashSet, а затем "сразу после" оно создается, вы добавляете к нему два элемента.

Это шаблон общего использования в макетных объектах для тестирования, например, в JMock, но также имеет другие полезные функции.

Надеюсь, что это поможет.

Ответ 4

Я считаю, что это плохая практика, потому что она создает бессмысленные подклассы, которые могут повлиять на использование памяти и производительность приложения. Во всяком случае, программа правильная, потому что конструктор суперкласса вызывается перед инициализаторами экземпляра. Поэтому, когда запускается ваш инициализатор, конструктор HashSet запускается, поэтому вызов add будет работать.