Всякий раз, когда вы не предоставляете явный вызов конструктору суперкласса, компилятор Java вставляет неявный вызов в конструктор суперкласса по умолчанию для вас (без аргументов). Это как если бы ваш B
конструктор был действительно:
public B() {
super();
a = 44;
diplay();
}
Вызов конструктора суперкласса вызывает конструктор P
, который вызывает diplay
. Объект действительно B
, поэтому при полиморфизме вызывается метод B
diplay
.
На данный момент у вас есть утечка вашего экземпляра подкласса, потому что он еще не полностью построен. Из-за этого B
переменная a
, которая скрывает * Переменная 1018 * a
, еще не инициализирована, поэтому она по-прежнему имеет значение по умолчанию, 0
.
Затем конструктор суперкласса P
завершается, и запускается остальная часть конструктора B
, который также вызывает diplay
. Этот вызов видит инициализированное значение 44
.
Конструктор не вызывается дважды; конструктор подкласса B
неявно вызывает конструктор суперкласса P
, и оба конструктора вызывают diplay
.
Возвращаясь к main
, вы ссылаетесь на поле a
, но ссылка на переменную типа P
. Полиморфизм полей отсутствует, поэтому, хотя во время выполнения объект является B
, извлекается значение P
*1038*, которое было инициализировано как 22
.
Этот код показывает, почему вообще не очень хорошая идея
- утечка
this
экземпляра объекта до завершения конструктора и
- намеренно объявляет переменные в подклассе с тем же именем, что и в суперклассе.