个人看法:创建子类对象时不会创建父类对象,只是会调用父类的构造器罢了。
理由如下:
创建一个SonTest类,代码如下:
import java.util.concurrent.TimeUnit;
class Father{
int x = 10;
public Father(){
System.out.println(this.x);
this.print();
x = 20;
}
public void print(){
System.out.println("f.x:"+x);
}
}
class Son extends Father{
int x = 30;
public Son(){
this.print();
x = 40;
}
@Override
public void print() {
System.out.println("s.x:"+x);
}
}
public class SonTest {
public static void main(String[] args) {
Son son = new Son();
// System.out.println(father.x);
try {
TimeUnit.SECONDS.sleep(600);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
说明:Son类继承了Father类,且重写了父类的print方法。
首先给出运行结果:
分析结果:可知父类构造器调用的this.print方法实则调用的是子类的相应方法,值得注意的是,父类中调用的x属于本类的x,而非子类的x。而之所以输出”s.x:0“是因为创建对象时调用的构造方法是先调用顶级父类的构造方法,然后逐次向下。在Father中调用子类的print方法时,子类的x还没进行显示初始化和构造器初始化,所以x=0.而此时父类中的this可以看作是new出来的Son类对象.
当然我们可以从另一个角度来看是否创建了父类对象:用到的工具为JProfiler:
通过该工具可以看到父类对象并没有创建。个人认为如果父类对象创建的话无疑会对大大增加jvm堆空间的负担.
那么如果子类对象赋值给父类引用又会发生什么呢?
把代码中的Son son = new Son()改为Father father = new Son();
执行结果为:
运行结果和上一次无异,分析的理由也是差不多的,读者可以自己尝试测试,如有不对的地方,请指正。
当然有一个需要注意的点是(题外话了):如果在Son类添加一个新的方法,father对象是无法调用的。
当然了,如果编辑器用的是idea的话,也可以下载插件--
来查看.class文件观察各指令的执行顺序,如:
我的理解到此结束,谢谢观看!!!