Java порядок инициализации классов и интерфейсов

Класс или интерфейс T  будет инициализирован сразу перед первым появлением следующих ситуаций:

  • T  является классом и создаётся экземпляр T.
  • Вызывается статический метод, объявленный в T.
  • Присваивается значение статическому полю, объявленному в T.
  • Используется значение статического поля T, которое не является константой.
  • T  — это top level класс, и вызывается assert, лексически вложенный в T.

Перед инициализацией класса сначала инициализируются все его суперклассы (если они не были инициализированы до этого), так же как и любые суперинтерфейсы, которые объявляют методы по умолчанию (default-методы). Инициализация интерфейса не приводит к инициализации его суперинтерфейсов.

Обращение к статическому полю приводит к инициализации только того класса или интерфейса, который объявляет это поле, даже если обращение к этому полю было по имени дочернего класса, дочернего интерфейса или класса, реализующего интерфейс.

Обращение к некоторым методам класса Class  из пакета java.lang.reflect  тоже приводит к инициализации класса или интерфейса.

Класс или интерфейс не инициализируются ни в каких других случаях, кроме описанных выше.

Обратите внимание, что компилятор может генерировать синтетические методы по умолчанию в интерфейсе. Такие методы приводят к инициализации интерфейса, даже если исходных код не привёл бы к его инициализации.

Статические блоки инициализации и инициализация статических переменных класса происходят в порядке их появления в объявлении класса.

Пример 1. Суперклассы инициализируются до подклассов:

Выведет в консоль:

 

Пример 2. Инициализируется только класс, объявляющий статическое поле, к которому было обращение:

Вывод в консоль будет таким:

 

Пример 3. Инициализация интерфейса не приводит к инициализации суперинтерфейсов.

Вывод в консоль будет следующим:

Обращение J.i  — это обращение к константе, поэтому оно не приводит к инициализации I.

Обращение K.j  — это обращение к полю, которое объявлено в интерфейсе J, и которое не является константой, поэтому оно приводит к инициализации полей интерфейса J, но не приводит к инициализации суперинтерфейса I, ни к инициализации K.

Не смотря на то что K  используется для обращения к j, интерфейс K  не инициализуется.

 

Источник:

https://docs.oracle.com/javase/specs/jls/se8/html/jls-12.html#jls-12.4

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *