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

Java继承中方法重写、构造器行为及变量遮蔽问题咨询

问题分析:为什么输出是-1而不是1001?

我们一步步拆解代码执行的全过程,就能明白问题出在哪:

1. 先搞清楚:void Base()不是构造器!

构造器的规则是没有返回值类型,你写的void Base()是一个普通实例方法,只是名字和类名相同而已。所以父类构造器里的Base()调用的是这个普通方法,不是递归调用构造器。

2. 子类的void Base()确实重写了父类的方法

因为方法签名完全一致(返回值void、方法名Base、无参数),所以父类构造器调用Base()时,会触发动态绑定,调用子类重写后的方法——这部分你的理解是对的,但接下来的变量初始化顺序才是关键。

3. Java对象初始化的顺序(核心原因!)

当你执行new Derived()时,初始化严格遵循以下顺序:

  • 先执行父类Base的实例变量初始化:id = 1000(此时父类的id是1000)
  • 执行父类Base的构造器:里面调用Base(),也就是子类的void Base()方法
  • 此时子类Derived的实例变量id还没完成显式赋值! 子类的实例变量初始化和构造器执行,必须等父类构造器完全执行完才会开始。
    • int类型的成员变量默认初始化值是0,所以此时子类的id是0
  • 子类Base()方法里执行--id:0减1得到-1,所以输出-1
  • 父类构造器执行完后,才会执行子类的实例变量初始化:id = 2000,但这时候输出已经完成了,这个赋值不影响结果

4. 为什么不是用父类的id?

变量的访问是静态绑定的,子类方法里的id默认指向子类自己的成员变量,而非父类的。如果要访问父类的id,需要用super.id,但你这里没写,所以用的是子类还没初始化完成的id。

总结:你预期的1001是假设调用父类的Base()方法操作父类的id,但实际上因为动态绑定调用了子类的方法,而子类的id此时还没赋值2000,还是默认的0,--之后就是-1。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 06:45:04