Java学习之子类对象实例化的执行顺序

Java学习之子类对象实例化的执行顺序

为得到子类对象实例化的执行顺序,定义一个父类AddClass和其子类SonAddClass,子类和父类中分别定义了三个构造函数,现在通过IDE的debug功能给子类的new语句设置断点,跟踪子类对象实例化的执行顺序。

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;
    }
    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());
    }
}

在对第一个

SonAddClass p1=new SonAddClass (2,3,5);

设置断点后,得到结果如下图所示:
在这里插入图片描述

采用断点调试的step into方法后,光标移至

SonAddClass (int x,int y,int z){
    super(x,y,z);  a=x+4;   b=y+4;  c=z+4;
}//此时x:2; y:3; z:5; a:0;b:0;c:0;

再次采用断点调试的step into方法后,光标移至

AddClass (int x,int y,int z) {
        this(x,y);
        this.z=z;
  }//光标移至this(x,y);此时x:2;y:3;z:5;

再次采用断点调试的step into方法后,光标移至

AddClass (int x,int y) {
        this(x);
        this.y=y;
    }//光标移至this(x);此时x:2;y:3

再次采用断点调试的step into方法后,光标移至

AddClass (int x) {
        this.x=x;
    }//光标移至this.x=x;此时x:2;

再次采用断点调试的step into方法后,光标移至

    private int x=0,y=0,z=0;//此时x:2;y:0;z:0;

再次采用断点调试的step into方法后,光标顺次向下移动

class AddClass {
    private int x=0,y=0,z=0;

    AddClass (int x) {
        this.x=x;//光标第一次到达;此时x:2;
    }
    AddClass (int x,int y) {
        this(x);//
        this.y=y;//光标第二次到达;此时x:2;y:3;
    }
    AddClass (int x,int y,int z) {
        this(x,y);
        this.z=z;//光标第三次到达;此时x:2;y:3;z:5;
    }
    public int add() {
        return x+y+z;
    }
}

上述过程过程说明,在子类创建一个类对象的时候,调用构造函数的顺序为:

1.先调用子类方法中的具有相同参数个数的构造函数;

2.从底向上调用父类的构造函数,即this()方法;

3.利用this指针从上向下对父类的属性进行赋值;

4.父类属性赋值完成后,调用子类中的构造函数,运用super()方法,对子类中的属性进行赋值。


在第一次调用断点调试的step into方法后再采用一次断点调试的step over方法后,光标移至

int a=0,b=0,c=0;//此时a:0;b:0;c:0;

再调用一次断点调试的step over方法后,光标移至

super(x,y,z);  a=x+4;   b=y+4;  c=z+4;//此时x:2;y:3;z:5;a:6; b:7; c:9;

同理,当对

SonAddClass p2=new SonAddClass (10,20);
SonAddClass p3=new SonAddClass (1);

分别设置断点后,会得到相同的结果。


总结:

1、JVM会读取指定路径下的SonAddClass.class文件,并加载进内存。并会先加载SonAddClass的父类AddClass。

2、在堆内存中开辟空间,分配地址。

3、并在对象空间中,对对象中的属性进行默认初始化。(不是显式初始化)

4、调用对应的构造函数进行初始化。

5、在构造函数中,第一行会先调用父类的构造函数进行初始化。

6、父类初始化完毕后,在对子类的属性进行显式初始化。

7、再进行子类构造函数的特定初始化。

8、初始化完毕够,将地址值赋值给引用变量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值