class Base {
private int i = 2; // 2
public Base() {
this.display(); // 3
}
public void display() {
System.out.println(i); //
}
}
class Derived extends Base {
private int i = 22; // 5
public Derived() {
i = 222; // 6
}
public void display() {
System.out.println(i); // 4
}
}
public class Test {
public static void main(String[] args) {
new Derived(); // 1
}
}
以上代码输出结果为0
代码行的注释表示执行顺序;
1:系统先为Derived对象分配内存空间,有两块内存空间分别存放Derived对象的两个i实例变量,一个是属于Base的一个是Derived的,此时这两个i实例变量的值都是0;
2:执行Derived类的构造器之前,先执行Base类的构造器。表面上看,Base类经过编译器处理后,其构造器包含如下两行代码:
i = 2;
this.display();
3: this.display();中的this在这里是指向Derived的,即实现子类的方法覆盖父类的方法
4:此时Derived的i还没有经过初始化,为0,故输出0
5:Derived的i初始化
6:Derived的构造器
----------------------------------
将Base类的构造器改为如下形式:
public Base() {
System.out.println(this.i);
this.display();
}
再次运行程序,将看到输出是2和0;
当变量的编译时类型和运行时类型不同时,通过该变量访问它所引用的对象的实例变量时,该实例变量的值由声明该变量的类型决定,但通过该变量调用它引用的对象的实例方法时,该方法行为由它实际所引用的对象来决定,一次当程序访问this.i时,它将访问Base类中定义的i实例变量,也就是将输出2;但执行 this.display()时则实际表现出Derived对象的行为,也就是输出Derived对象的i实例变量,即为0。