Найти в Дзене
Java

☕ Вопрос с собеседования: Статический блок и порядок инициализации

☕ Вопрос с собеседования: Статический блок и порядок инициализации

🔍 Условие:

Что выведет следующий код и почему?

public class InitializationPuzzle {

static {

System.out.println("Static block 1");

}

public static void main(String[] args) {

Child.doSomething();

}

}

class Parent {

static {

System.out.println("Parent static block");

}

}

class Child extends Parent {

static {

System.out.println("Child static block");

}

static void doSomething() {

System.out.println("Child method");

}

}

❓ Вопрос:

Какой будет порядок вывода? Почему результат может удивить даже опытных Java-разработчиков?

🔍 Разбор:

✅ Что происходит по шагам:

1️⃣ При запуске программы сначала загружается класс `InitializationPuzzle`. Его статический блок выполняется сразу:

Static block 1

2️⃣ Далее вызывается Child.doSomething(). Теперь происходит инициализация класса `Child`. В Java при инициализации класса-потомка сначала загружается родительский класс, если он ещё не был загружен.

- Инициализация Parent:

Parent static block

- Инициализация Child:

Child static block

3️⃣ Наконец выполняется метод doSomething():

Child method

---

✅ Ожидаемый полный вывод:

Static block 1

Parent static block

Child static block

Child method

💥 Подвох:

• Многие разработчики думают, что раз doSomething() просто статический метод, может выполниться только он.

• Однако Java гарантирует, что перед выполнением любого статического метода класс будет полностью инициализирован.

• Также важно помнить, что при инициализации класса наследника сначала выполняются статические блоки родителя.

🛡️ Лайфхак:

Если вы хотите убедиться, что родительский класс не инициализируется при доступе к статическим полям/методам потомка, нужно использовать константы (static final), которые компилируются напрямую в байткод и не требуют загрузки класса.

✅ Вывод:

• Java строго инициализирует классы в порядке наследования перед вызовом любых статических методов.

• Даже вызов одного «безопасного» статического метода потомка затянет за собой загрузку родителя.

• Такие задачи хорошо проверяют понимание механизма класслоадеров и инициализации классов в JVM.

💡 Бонус-вопрос:

Что изменится, если вы замените doSomething() на чтение static final поля в Child? Будет ли тогда инициализирован Parent?

@javarush