Класс C
переопределяет A.foo()
, а полиморфизм активен даже в конструкторе Java. Поэтому, когда конструктор в A
вызывает foo()
, когда мы создаем экземпляр C
, это C.foo()
, который фактически вызывается.
C.foo()
в свою очередь, выводит B.i
, так что мы могли бы ожидать 6
быть распечатаны - но переменная экземпляра Инициализаторы выполняется только после того, как суперкласса конструкторами, поэтому в момент исполнения, B.i
0.
в принципе, порядок исполнения конструктора:
- Выполнить сцепленные конструкторы, либо явно
this(...)
приковать к другому конструктор в том же классе или явно super(...)
для привязки к конструктору в суперклассе, или неявно super()
, чтобы привязать к беспараметрическому конструктору в суперклассе.
- Для конструкторов, которые были привязаны к конструктору суперкласса, выполните инициализаторы переменных.
- Исполнить код в теле конструктора
переписывания кода, чтобы избежать использования инициализаторы переменных и переменная затенение делает это более ясным, в то же время сохраняя код эквивалент:
public class A {
int ai;
public A() {
super();
ai = 5;
foo();
}
public void foo() {
System.out.println(ai);
}
}
class B extends A {
int bi;
public B() {
super();
bi = 6;
}
}
class C extends B {
int ci;
public C() {
super();
ci = 7;
}
public void foo() {
System.out.print(bi);
}
public static void main(String[] args) {
C c = new C();
}
}
Как и в сторону, то «переменная скрытие» часть этого не вступает в игру, если вы делаете все свои поля частными, и это то, что я бы рекомендовал. Это просто оставляет проблемы при вызове виртуальных методов от конструктора, что, как правило, является плохой идеей из-за ожидая, что объект сможет работать до того, как у него будет возможность полностью инициализироваться, и, возможно, удивительное время выполнения переменной инициализатора.
Если вы избегаете вызывать виртуальные методы из конструкторов, то даже время переменных инициализаторов становится неуместным - по крайней мере почти всегда.
Не после того, как конструктор - но первая часть скомпилированного тела конструктора * после * вызов конструктора суперкласса. –