You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java实例化子类时父类构造调用print输出00的原因是什么?

Java继承构造调用重写方法问题解答

核心结论

  • 父类构造方法中调用的print()是子类Derived重写后的版本
  • 输出00是因为子类自定义的实例成员还未完成显式初始化,仍为int类型的默认值0

问题代码

public class Base {
    private int member1 = 1;
    private int member2 = 2;

    public Base() {
        System.out.println("base ctor");
        print();
    }

    public void print() {
        System.out.println(member1 + "" + member2);
    }
}

class Derived extends Base {
    private int member3 = 3;
    private int member4 = 4;

    public Derived() {
        System.out.println("derived ctor");
        print();
    }

    public void print() {
        System.out.println(member3 + "" + member4);
    }
}

class Test{
    public static void main(String[] args) {
        Derived d = new Derived();
    }
}

实际运行输出

base ctor
00
derived ctor
34

原理说明

1. 方法调用的动态分派规则

Java的非私有实例方法采用动态分派机制,方法的实际执行版本由对象的运行时实际类型决定。本次代码中创建的是Derived类型的对象,所以所有对print()的调用默认都会执行子类重写的实现,哪怕该调用是写在父类的构造方法中。

同时父类的member1、member2是private修饰,子类无法直接访问,子类重写的print()方法操作的完全是自己定义的member3、member4两个成员,和父类的成员无关。

2. 继承类的实例化执行顺序

当创建子类对象时,JVM的执行流程严格按照以下顺序:

  1. 为整个子类对象分配内存空间,所有实例成员(包括父类继承的、子类自己定义的)全部初始化为对应数据类型的默认值,int类型的默认值为0,此时member1=0,member2=0,member3=0,member4=0
  2. 进入子类构造方法,首先隐式调用父类构造方法:
    • 先执行父类的实例成员显式初始化:member1=1,member2=2
    • 执行父类构造方法的代码:
      1. 打印base ctor
      2. 调用print()方法,动态分派到子类实现,此时子类的member3、member4还没有进行显式初始化,仍然是默认值0,所以输出00
  3. 父类构造方法执行完毕,回到子类流程,执行子类的实例成员显式初始化:member3=3,member4=4
  4. 执行子类构造方法的剩余代码:
    1. 打印derived ctor
    2. 调用print()方法,此时子类成员已经完成赋值,输出34

注意:在构造方法中调用可被重写的实例方法是非常危险的操作,很容易因为子类成员未完成初始化导致逻辑异常,实际开发中应当尽量避免这种写法。


内容的提问来源于stack exchange,提问作者NoobCoder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 12:24:04