关于this究竟表明的案例

咱们知道,父类是不能访问子类的实例变量的。但这里有一个特殊的案例java

class Base {
    private int i = 2;
    public Base(){
         System.out.println(this.i);
         this.display();
         //System.out.println(this.getClass());
         //this.test();
    }
    public void display(){
         System.out.println(i);
    }
}
public class Sub extends Base {
     private int i = 22;
 
     public Sub(){
         i = 222;
     }
 
     public void display(){
         System.out.println(i);
     }
 
     public static void main(String[] args) {
         new Test(); ①
     }
 
     public void test(){
            
     }
}

结果却出人意料,并非2, 2.而是2, 0.函数

分析:在①出代码,新建了Sub对象,在Sub类的构造函数中,先隐式调用Base类的无参构造函数。在分析Base的构造函数以前,咱们首先要明白三点:this

1)Java类的对象并非由构造函数建立的,而是在构造函数赋初值以前,就已经给类成员变量分配了内存空间,而且内存内的值为空值。并且类中的定义时即赋值的成员变量和非静态代码块中初始化元素,都是先分配内存(存储默认值),而后在归并到构造函数中赋初始值,并按前后顺序排列在构造函数本来的代码以前。code

2)关于子类与父类有多个同名实例变量的问题,要知道,子类的实例变量并不能覆盖父类的同名实例变量。因此在实例化Sub类时,要先分配两块内存空间,用来存储父类的i和子类的i,这时两个i的值都为0。对象

3)当this在构造器中时,表明正在初始化的对象。从源代码来看,this在Base的构造器中执行。可是实际上,如今正在初始化的Java类是Sub,由于是在Sub的构造器中隐式地调用了父类的默认构造器,因此this是Sub类,这一点能够从this.getClass()验证。内存

那么问题来了,this表明Sub类,但this.i却输出2,而this.display()却输出0。get

这是由于this位于Base的构造器中,它的编译类型是Base,可是它引用的对象则是一个Sub类型,即它的运行时类型是一个Sub类型,这一点能够由this.test()验证,由于这回编译不经过。编译

总结:当变量的编译时类型和运行时类型不一样时,当经过该变量来访问它所引用的对象的实例变量时,该实例变量的值由声明它的类型决定,但当经过该变量来访问它所引用对象的实例方法时,该方法行为将由它所引用的对象类型决定。class

因此this.i的值为Base中的i,this.display()为Sub中的方法,i为0.test

相关文章
相关标签/搜索