当编译时门类与运行时类型不同时

当编译时类型与运行时类型不同时
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。