В каком порядке выполняются статические блоки и конструкторы в Java
Что проверяют
Знаете ли вы порядок инициализации до деталей. Вопрос любят задавать с наследованием, где ответ уже не очевиден.
Как отвечать
Разделите два момента: инициализация класса (один раз при первой загрузке) и инициализация объекта (при каждом new).
При загрузке класса выполняются статические поля и статические блоки в порядке их объявления в файле. Сначала это происходит для родителя, потом для наследника.
При создании объекта порядок такой:
- вызывается конструктор наследника, но его первым делом передаётся управление конструктору родителя (
super()неявно или явно); - в родителе выполняются поля экземпляра и блоки инициализации в порядке объявления, затем тело его конструктора;
- возвращаемся в наследник: выполняются его поля и блоки инициализации, затем тело конструктора.
class Parent {
static { System.out.println("1 static Parent"); }
{ System.out.println("3 init Parent"); }
Parent() { System.out.println("4 ctor Parent"); }
}
class Child extends Parent {
static { System.out.println("2 static Child"); }
{ System.out.println("5 init Child"); }
Child() { System.out.println("6 ctor Child"); }
}Полезно добавить, когда класс вообще загружается: при первом создании объекта, обращении к статическому члену или через Class.forName. Обращение к константе времени компиляции (static final с литералом) загрузку не вызывает вовсе.
Где спотыкаются
Думают, что статический блок выполняется при каждом создании объекта.
Забывают про блоки инициализации экземпляра и про то, что они идут до тела конструктора.
Вызывают переопределяемый метод из конструктора родителя: он уйдёт в реализацию наследника, поля которого ещё не инициализированы, и вернёт null или ноль.