tay*_*pen 3 java variables inheritance overriding initialization
我定义了三个类(A,B,C):
public class A {
int i = 5;
public A() {
foo();
}
public void foo() {
System.out.println(i);
}
}
class B extends A {
int i = 6;
}
class C extends B {
int i = 7;
public void foo() {
System.out.print(super.i);
}
public static void main(String[] args) {
C c = new C();
}
}
Run Code Online (Sandbox Code Playgroud)
预期结果是:6但程序返回:0
有人能解释一下结果吗?你的帮助将不胜感激.
类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();
}
}
Run Code Online (Sandbox Code Playgroud)
顺便说一句,如果您将所有字段设为私有字段,那么"变量隐藏"部分就不起作用了,这就是我推荐的内容.这就留下了从构造函数调用虚方法的问题,这通常是一个坏主意,因为期望一个对象能够在它有机会完全初始化之前工作,以及可能令人惊讶的变量初始化程序执行时间.
如果你避免从构造函数调用虚方法,那么即使变量初始化器的时间也变得无关紧要 - 至少几乎总是如此.