覆盖了父类的成员变量引发的问题
this代表什么呢?代表当前类的某个对象?请看下面这段代码:
package cn.com.wg.task01; public class CallOrder { class Base { private int i = 2; public Base() { System.out.println(this); this.display(); } public void display() { System.out.println("Base " +this.i); } } class Child extends Base { private int i = 22; public Child() { System.out.println(this); i = 222; } public void display() { System.out.println("Child " + i); } } public void init() { new Child(); } public static void main(String[] args) { new CallOrder().init(); } }
输出结果是什么呢?
cn.com.wg.task01.CallOrder$Child@d0da1d8
Child 0
cn.com.wg.task01.CallOrder$Child@d0da1d8
此时,子类和父类构造函数的this代表同一个对象!!!this理解为代表调用该方法的那个对象更合适。
我们知道子类的构造函数会调用父类的构造函数(如果没有显示的调用,默认隐式调用无参的构造函数),所以在该程序中,父类的无参构造函数会在子类的构造函数中调用。因此,子类和父类构造函数的this代表同一个对象。
那么,输出的“Child 0”怎么解释呢?这里就牵涉到JVM的内存分配了。下面简单介绍。
当JVM遇到new关键字时,就会开始在内存中给对象分配空间。一个简单的java对象的在内存中包括三个部分:对象头、变量、填充区域。new结束后,变量域是初始化后的值(即boolean为false,char为'\0',其他基本类型为0,对象为null)。当遇到new后的类名是才开始执行我们代码中的构造函数。
这是用javap看到的class文件中Child的构造函数内容:
这是Base类的构造函数:
在Base类的构造函数中调用display方法,显然是调用在Child里写的display方法,i也是Child里的i。但是Child中,i的初始化是在调用display之前完成的,所以此时i=0;
如果我们把Child里的display去除,会输出什么呢?“Base 2”。此时调用的display肯定是Base里的了,而且i的初始化在调用display之前,而且这个i是在Base中声明的。那么,问题来了,Child对象中有几个i变量呢?“2个”。
这些问题全是由子类中覆盖了父类的成员变量造成的,所以不要轻易覆盖父类的成员变量,而且很少一定要这么做。
上一篇: mac utraledit 破解
推荐阅读
-
子类可以继承父类的一切方法,成员变量,甚至是私有的,但是却不能够访问这些私有的成员变量和方法
-
[Java] 父类和子类拥有同名的成员变量(fields)的情况
-
C++简单的子类继承父类访问父类的成员函数和成员变量
-
JAVA中的父类私有成员变量的继承问题
-
问题:C++类的静态成员变量如何初始化
-
子类可以继承父类的一切方法,成员变量,甚至是私有的,但是却不能够访问这些私有的成员变量和方法
-
[Java] 父类和子类拥有同名的成员变量(fields)的情况
-
覆盖了父类的成员变量引发的问题
-
静态变量、实例变量初始化时机,以及子类隐藏父类成员时,创建子类对象的一些问题
-
继承:子类可以继承父类的私有成员变量吗??