← Назад к вопросам

Какая операция внутри объекта произойдет раньше всего?

2.3 Middle🔥 111 комментариев
#ООП#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Порядок инициализации объекта в Java

Это классический вопрос про жизненный цикл объекта в Java. Есть чёткий порядок, в котором всё происходит.

Порядок операций при создании объекта

Основной порядок:

  1. Static инициализация (один раз при загрузке класса)
  2. Инициализация полей экземпляра (default значения)
  3. Инициализаторы полей
  4. Инициализаторный блок
  5. Конструктор

Пример с подробным разбором

public class Example {
    static {
        System.out.println("1. Static блок");
    }
    static int staticField = initStatic();
    static int initStatic() {
        System.out.println("2. Static поле инициализация");
        return 10;
    }
    
    int instanceField = initInstance();
    int initInstance() {
        System.out.println("3. Instance поле инициализация");
        return 20;
    }
    
    {
        System.out.println("4. Instance инициализаторный блок");
    }
    
    public Example() {
        System.out.println("5. Конструктор");
    }
}

При создании объекта вывод будет:

    1. Static блок
    1. Static поле инициализация
    1. Instance поле инициализация
    1. Instance инициализаторный блок
    1. Конструктор

С наследованием

Когда есть наследование, сначала полностью инициализируется parent, потом child:

class Parent {
    static {
        System.out.println("1. Parent static");
    }
    int parentField = initParent();
    int initParent() {
        System.out.println("2. Parent field init");
        return 1;
    }
    {
        System.out.println("3. Parent init блок");
    }
    public Parent() {
        System.out.println("4. Parent конструктор");
    }
}

class Child extends Parent {
    static {
        System.out.println("5. Child static");
    }
    int childField = initChild();
    int initChild() {
        System.out.println("6. Child field init");
        return 2;
    }
    {
        System.out.println("7. Child init блок");
    }
    public Child() {
        System.out.println("8. Child конструктор");
    }
}

При new Child() выведет:

    1. Parent static блок
    1. Child static блок
    1. Parent field init
    1. Parent init блок
    1. Parent конструктор
    1. Child field init
    1. Child init блок
    1. Child конструктор

Опасный случай: вызов переопределённого метода в конструкторе

class Parent {
    public Parent() {
        printName();
    }
    public void printName() {
        System.out.println("Parent");
    }
}

class Child extends Parent {
    String name;  // Ещё null!
    
    public Child() {
        super();
        name = "Child";
    }
    
    @Override
    public void printName() {
        System.out.println(name);  // NullPointerException!
    }
}

Эта программа выведет null! Потому что Child.printName() вызовется из Parent конструктора, до того как name будет инициализирована.

Практический совет

  1. Не вызывай переопределяемые методы из конструктора
  2. Будь осторожен со static инициализацией — это может быть дорого
  3. Помни, что поля инициализируются в порядке объявления
  4. Static инициализация происходит один раз, при первой загрузке класса

Краткий ответ на вопрос

Что произойдёт раньше всего?

Static инициализация — но только при первой загрузке класса. Если класс уже загружен, то инициализация полей экземпляра происходит раньше конструктора.