您的位置:首页 > 其它

关于"多态"形式的成员变量问题(关于this究竟代表的案例)

2017-03-13 10:16 211 查看
我们知道,父类是不能访问子类的实例变量的。但这里有一个特殊的案例
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的构造函数之前,我们首先要明白三点:

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

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。

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

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

所以this.i的值为Base中的i,this.display()为Sub中的方法,i为0.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: