Инициализируются ли поля перед кодом конструктора на Java?
Может ли кто-нибудь объяснить вывод следующей программы? Я думал, что конструкторы инициализируются перед переменными экземпляра. Поэтому я ожидал, что выход будет "XZYY".
class X {
Y b = new Y();
X() {
System.out.print("X");
}
}
class Y {
Y() {
System.out.print("Y");
}
}
public class Z extends X {
Y y = new Y();
Z() {
System.out.print("Z");
}
public static void main(String[] args) {
new Z();
}
}
Ответы
Ответ 1
Правильный порядок инициализации:
- Статические инициализаторы инициализации и статические блоки инициализации в текстовом порядке, если класс ранее не был инициализирован.
- вызов super() в конструкторе, явный или неявный.
- Инициализаторы переменных экземпляра и блоки инициализации экземпляра в текстовом порядке.
- Оставшееся тело конструктора после super().
См. разделы §2.17.5-6 спецификации виртуальной машины Java.
Ответ 2
Если вы посмотрите на декомпилированную версию файла класса
class X {
Y b;
X() {
b = new Y();
System.out.print("X");
}
}
class Y {
Y() {
System.out.print("Y");
}
}
public class Z extends X {
Y y;
Z() {
y = new Y();
System.out.print("Z");
}
public static void main(String args[]) {
new Z();
}
}
Вы можете обнаружить, что переменная экземпляра y
перемещается внутри конструктора, поэтому последовательность выполнения выглядит следующим образом
- Вызов конструктора
Z
- Он запускает конструктор по умолчанию
X
- Вызывается первая строка конструктора
X
new Y()
.
- Печать Y
- Печать X
- Вызов первой строки в конструкторе Z
new Y()
- Печать
y
- Печать Z
Все переменные экземпляра инициализируются с помощью инструкций конструктора.
Ответ 3
Порядок инициализации выглядит следующим образом:
- Статические переменные и блоки инициализации в порядке их появления
- Вызов
super()
в теле конструктора
- Переменные экземпляра и блоки инициализации в порядке их появления
- Остальная часть тела конструктора
Из раздела §12.5 в спецификации виртуальной машины Java.
Ответ 4
Последовательность инициализации задана в JLS 12.5:
1. Сначала выделяется память для нового объекта
2. Затем все переменные экземпляра в объекте (включая те, которые определены в этом классе и все его суперклассы) инициализируются значениями по умолчанию
3. Наконец, вызывается конструктор.
fooobar.com/info/78207/...