Java子类对象的初始化顺序
一、任务:利用idea的断点调试,弄清楚Java的子类对象在被创建时,所调用的代码的顺序
考虑如下的代码,SonAddClass继承自父类AddClass,父类AddClass中重载三个构造方法,并可以互相调用,子类重载了三个构造方法,并都使用super对父类成员进行初始化,我们在子类对象的main方法中设置断点,来观察子类对象创建时代码的运行过程
父类
class AddClass {
private int x=0,y=0,z=0;
AddClass (int x) {
this.x=x;
}
AddClass (int x,int y) {
this(x);
this.y=y;
}
AddClass (int x,int y,int z) {
this(x,y);
this.z=z;
}
public int add() {
return x+y+z;
}
}
子类
public class SonAddClass extends AddClass{
int a=0,b=0,c=0;
SonAddClass (int x) {
super(x); a=x+7;
}
SonAddClass (int x,int y){
super(x,y); a=x+5; b=y+5;
}
SonAddClass (int x, int y,int z){
super(x,y,z); a=x+4; b=y+4; c=z+4;
}//super(x,y,z)如果去掉会如何?
public int add() {
System.out.println("super:x+y+z="+super.add());
return a+b+c;
}
public static void main(String[] args){
SonAddClass p1=new SonAddClass (2,3,5);
SonAddClass p2=new SonAddClass (10,20);
SonAddClass p3=new SonAddClass (1);
System.out.println("a+b+c="+p1.add());
System.out.println("a+b="+p2.add());
System.out.println("a="+p3.add());
}
}
二、运行结果
首先,调用创建子类对象的代码后,根据用户算传递的参数类型和个数,调用上图所示的构造函数,在子类的构造函数中,调用了父类的构造函数。
2.
进入到父类的构造函数后,使用this(x,y)调用父类中重载的构造函数
3.
然后再次调用重载的构造函数
4.
5.
在每一次的构造函数调用完后,都会调用父类的静态代码块,并不断回溯,直到子类的构造函数中,在执行子类的静态代码块,在执行普通代码块。
三、总结
Java在创建子类对象时,各代码的执行顺序为:首先执行父类静态代码块及父类静态成员变量,在执行完毕后回溯到子类的构造函数,执行子类静态代码块及子类静态成员变量,在执行父类普通代码块及父类成员变量,然后是父类的构造函数,再是子类普通代码块及子类成员变量,最后是子类构造器中的普通代码。