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