日期:2014-05-20  浏览次数:20683 次

构造器内部的多态
class Test1 {
void f(){
System.out.println("Test1.f()");
}
Test1(){
System.out.println("Test1() before f()");
f();
System.out.println("Test1() after f()");
}
}

class Test2 extends Test1 {
private int a = 1;

Test2(int a){
this.a = a;
System.out.println("Test2.Test2().a = " + a);
}

void f(){
System.out.println("Test2.f().a = " + a);

}
}

public class Test {
public static void main(String[] args){
new Test2(5);
}
}


输出结果是:

Test1() before f()
Test2.f().a = 0
Test1() after f()
Test2.Test2().a = 5


大家能帮忙解释一下这个初始化的顺序吗?在调用父类构造器时,存在一个多态,程序运行到f()时,是不是还没有编译子类的成员变量 private int a = 1???

------解决方案--------------------
没有显式的调用super,就会调用父类的默认构造函数。调用顺序是:父类构造函数-->子类构造函数(先执行private int a = 1;然后在执行子类构造函数内的语句)。
所以在父类的构造函数内部调用f()方法时,因为实际类型是Test2,调用的是子类的f()方法,a的值为0。等到执行子类构造函数时,a已经是1了。
------解决方案--------------------
然后你Test2的构造函数里System.out.println("Test2.Test2().a = " + a);输出的是传入参数a,传入5,所以输出5.
------解决方案--------------------
在每一级构造函数初始化之前,先给成员变量赋默认值,之后上溯父类,一直到Object,然后再往下执行,到每一级时,给成员变量显示赋值,再执行构造函数的语句。一直到最后那个子类。
楼主的 程序,在父类执行f()时,因为多态的特性,实际执行的是子类的f(),这时子类里的 a=0(默认值)。
------解决方案--------------------
子类都会先调用父类的构造
因为有着依赖
无参的就直接调
有参要用super显示调用
------解决方案--------------------
探讨

没有显式的调用super,就会调用父类的默认构造函数。调用顺序是:父类构造函数-->子类构造函数(先执行private int a = 1;然后在执行子类构造函数内的语句)。
所以在父类的构造函数内部调用f()方法时,因为实际类型是Test2,调用的是子类的f()方法,a的值为0。等到执行子类构造函数时,a已经是1了。

------解决方案--------------------
没有显式的调用super,就会调用父类的默认构造函数