子父类构造函数-子类的演化过程
先看下边的程序运行的结果是什么
这段程序 的运行结果是
zi show....1...0
zi show....2....10
zi show....1...10
原因是,看下图内存分析 图
原因:
这里是程序 刚开始 执行的地方
Zi zi = new Zi();
程序 会先执行子类的构造函数 ,在子类的构造方法中,有一句super()语句,当代码执行到这一句后,程序 会进入Fu类中运行,
这里,由于父类 的构造方法中,也有一句super(),它默认继承Object类,不做考虑,当它运行到Show()方法时,由于子类重写了父类的show()方法,所以这时程序 会调用子类的show()方法,由于子类对象这会在堆中并没有进行赋值操作 ,所以这时的num = 0; (注意这里的num会是默认值 0),所以它会先运行子类的show()方法,并且num = 0;
然后父类 的构造方法中,会继续执行return语句,父类 弹栈,然后子类的构造方法中,super(),调用完后,这里子类中的num变量会被赋值为10,最后
Zi zi = new Zi();这一句代码执行完毕 ,
zi.show();
再执行这一句代码,num = 10;
一个对象实例化过程
Person p = new Person();
1,JVM会读取指定的路径下的Person.class文件,并加载 进内存,并会先加载Person的父类 (如果有直接的父类 的情况下)
2,在堆内存中开辟空间,分配 地址,
3,并在对象空间中,对对象中的属性进行默认初始化。
4,调用对应的构造函数进行初始化
5,在构造函数 中,第一行会先到调用父类 中构造函数 进行初始化,
6,父类 初始化完毕 后,在对子类的属性进行显示 初始化。
7,在进行子类构造函数的特定初始化
8,初始化完毕 后,将地址值 赋值给引用变量
下面的例子加上了构造代码块
class Fu{ { System.out.println("fu contructor ...");---> 1,第一步 show(); ---------------------------------->子类重写父类方法,运行子类的方法 } Fu(){ super();//Object //显示初始化 //构造代码块初始化 System.out.println("fu run");-----------------> 3.第三步 } public void show(){ System.out.println("fu show ..."); } } class Zi extends Fu{ int num = 9; { System.out.println("zi contructor ..."+num);---->4.第四步 num = 10; } Zi(){ super();//注意:super调用完之后,中间是下边这两步 //显示初始化 //构造代码块初始化 System.out.println("zi run ..."+num); ------------>5.第五步 } @Override public void show() { System.out.println("zi show ..."+num);-------------> 2.第二步 } -------------> 6.第六步 } public class DemoSummary { public static void main(String[] args){ new Zi().show();------------------------------------>程序入口 } }
运行结果是
fu contructor ...
zi show ...0
fu run
zi contructor ...9
zi run ...10
zi show ...10