本节主要讲构造器的调用过程
构造器
接下来先看个例子
class Demo{
static int x= 1;
int y = 1;
static {
System.out.println(“static code …x “+x ):
}
{
System.out.println(“cons code ..y=”+y);
}
Demo(){
System.out.println();
}
}
class CreateObjectTest{
public static void main(String[] args){
Demo d = new Demo();
}
}
运行命令
javac CreateObectTest.java
java CreateObectTest
操作过程
//省略了CreateObjectTest加载,和运行。
1.加载Demo.class 文件进方法区,并进行空间分配
2.如果有静态变量先默认初始化,显示初始化。
3.如果有静态代码块,要先执行,一次
4.通过new 在堆内中开辟空间,并明确首地址。
5.对对象中的属性进行默认初始化。
6.调用对应的构造函数进行初始化。
*7.构造函数内部
7.1调用父类构造函数super();//后面解释
7.2成员变量的显示初始化;
7.3构造代码块初始化;
7.4构造函数内容自定义内容初始化。
8.对象初始化完毕
重点理解构造函数内部。
继承
子类中的构造函数为什么有一句隐式super()
原因:子类会继承父类中的内容,所以子类在初始化时,必须先的到
父类中去执行父类的初始化动作。才可以方便的使用父类的内容。
当父类中没有空参数构造函数时,子类的构造函数必须同构显示的
super语句去指定要访问的父类的构造函数。
例子:
class Fu{
private int num1 = 3 ;
//创建子类的时候 子类对象的父类内存空间有num1,只是子类不能直接访问。
int num =3 ;
}
class Zi extends Fu{
int num =4 ;
}
class ExtendsDemo{
public static void main(String[] args){
Zi z = new Zi();
}
操作过程
1.当Zi z= new Zi();会加载Fu 后加载 Zi
2.new 堆内存中开辟空间
**会有两个num 一个是对象中父内存的 另一个是在对象中的
num =0 , num= 0
3.调用class Zi 构造器,
super() 调用父类的默认构造器。
4.父类的构造器里(这里其实也有super())先实行成员变量显示初始化
然后构造代码块初始化。
5.执行Zi构造器的成员变量显示初始化
然后执行构造代码块的初始化。
6.完成
拓展
如果子类的构造函数第一行写了this调用了本类其他构造函数,
那么super调用父类的语句还有吗?
当然是没有,没有的。因为this()或者super(),只能定义在构造函数的第一行,
因为初始化动作要先执行。
例子:
class thisDemo{
public thisDemo(){
//这个还是有隐式的super()
}
public thisDemo(int x ){
this()//跳转到默认构造器
}
}
这里一看就知道了,很明显是合理的。