父类构造函数-子类的实例化过程
例子:
class Fu{
Fu() //构造函数
{
super(); //默认隐藏
show();
return; //默认隐藏
}
void show()
{
System.out.println("fu show");
}
}
class Zi extends Fu{
int num = 8;
Zi() //构造函数
{
super(); //默认隐藏
return; //默认隐藏
}
void show()
{
System.out.println("zi show...."+num);
}
}
public class Demo {
public static void main(String[] args){
Zi z = new Zi();
z.show();
}
}
运行结果:
内存图解
main函数进栈,然后z
new了Zi()
对象
new Zi() 对象 准备把类加载进方法区,然后这时发现,这类中,还有一个父类,于是把它们一起加载进方法区
随着类的加载完毕,于是执行new Zi();于是在堆内存开辟了一块空间
num 默认初始化为0
然后执行了 Zi() 里面的构造函数,构造函数进栈
然后执行构造函数里面的内容
里面有个默认的super();执行父类的,刚好我们这里继承了父类,于是父类的构造函数也进栈了
执行Fu类构造函数里面的内容,里面有个show()方法,于是通过this地址找到了堆内存开辟的内存,先是在Zi里面找,发现有show,于是执行.
这也是为什么我们第一个会输出:zi show....0
的原因
然后return;结束,然后退栈,然后num就开始显示初始化为8.
这里如果Zi的方法没有叫show()的,那么在找不到的情况下,就会去到Fu里面找
可以自己修改代码测试一下.
Zi里面的构造函数super内容执行完之后,往下执行,然后遇到return;
于是也退栈
全部执行完之后,就把堆内存开辟的内存的地址给到了z,z就指向了它
然后这时执行z.show();也就输出了 zi....show8
了.
一个对象实例化的过程
Person p = new Person();
1.JVM虚拟机会读取指定路径下的Person.class文件,并加载进内存
并会先加载Person的父类(如果有直接父类的情况下).
2.在堆内存中开辟空间,分配地址.
3.并在对象空间中,对对象中的属性进行默认初始化.
4.调用对应的构造函数进行初始化
5.在构造函数中,第一行会先调用父类中的构造函数进行初始化
6.父类初始化完毕后,再对子类属性进行显示初始化.
7.在进行子类构造函数的特定初始化
8.初始化完毕后,将地址赋值给引用变量