本文揭示了java继承场景下因复制构造函数逻辑错误导致成员变量始终为0的根本原因,并提供正确实现方式及完整调试方案。
本文揭示了java继承场景下因复制构造函数逻辑错误导致成员变量始终为0的根本原因,并提供正确实现方式及完整调试方案。
在Java面向对象编程中,构造函数的正确实现对对象状态初始化至关重要。上述代码看似结构清晰,却因一个关键逻辑反转——复制构造函数中赋值方向错误——导致所有实例字段(length、width、height、weight)始终为默认值 0。
问题核心出现在 Box 类的复制构造函数中:
Box(Box obj) {
obj.length = length; // ❌ 错误:将 this.length(未初始化,为0)赋给 obj.length
obj.width = width; // 同样错误地覆盖传入对象的值
obj.height = height;
}该写法实际是用当前新对象(尚未初始化)的字段值(默认为 0)去覆盖参数对象 obj 的字段,不仅未能完成复制,反而破坏了传入对象的状态,更导致新对象自身字段仍保持默认 0。正确做法应是以 obj 为源,向 this 赋值:
Box(Box obj) {
this.length = obj.length; // ✅ 正确:用 obj 的值初始化当前对象
this.width = obj.width;
this.height = obj.height;
}同理,WeightBox 类中的复制构造函数也存在相同错误:
WeightBox(WeightBox obj) {
super(obj); // 此时 super(obj) 会调用 Box(Box obj),若其有误则连锁失败
obj.weight = weight; // ❌ 错误:应为 this.weight = obj.weight;
}应修正为:
WeightBox(WeightBox obj) {
super(obj); // 先正确复制父类字段
this.weight = obj.weight; // ✅ 正确复制子类字段
}此外,还需注意以下关键点以确保健壮性:
- 字段可见性:Box 中的 length、width、height 为包级私有(默认访问修饰符),WeightBox 可直接访问,但建议未来升级为 protected 以明确设计意图;
- volume() 方法无需存储中间值:vol 字段非必需,可直接 return length * width * height;,避免冗余状态;
- 构造链完整性:WeightBox(double l, double w) 调用 super(l) 正确触发 Box(double l),但需确认 Box(double l) 已正确定义(代码中已存在,无误)。
✅ 修正后的完整运行示例输出应为:
Box no. 1 length = 10.0 width = 20.0 height =30.0 volume = 6000.0 Weight = 40.0 Box no. 2 length = 10.0 width = 10.0 height =10.0 volume = 1000.0 Weight = 20.0 Box no. 3 length = 10.0 width = 20.0 height =30.0 volume = 6000.0 Weight = 40.0
总结:在编写复制构造函数时,务必牢记“this ← obj”原则——所有赋值操作均应以参数对象为数据源,当前对象为接收方。这是避免初始化失效、保障继承链状态一致性的基本准则。

















