Java向上转型中构造器赋值与子类字段重定义的访问差异问题
为什么向上转型后子类字段赋值的两种情况结果不同?
这个问题的核心在于:Java的实例字段不支持多态,只有方法具备多态特性,当子类定义与父类同名的字段时,会触发**字段隐藏(Field Hiding)**机制,这和方法重写完全是两回事。
第一种情况:子类直接修改父类继承的字段
当子类没有重新定义name和age字段时,子类对象中只存在一套从父类继承来的name和age字段。子类构造器中的this.name = "Child name",本质是修改了继承自父类的字段值。
向上转型为Parent类型后,引用p指向的是子类对象,此时访问的字段已经被子类修改过,所以输出Child name。
第二种情况:子类重新定义同名字段(字段隐藏)
当子类重新定义public String name;和public int age;时,子类对象中会同时存在两套字段:
- 父类的
name(初始值Parent name)和age(初始值30) - 子类自己的
name(赋值为Child name)和age(赋值为10)
子类构造器中的this.name = "Child name",只是给子类自己的字段赋值,父类的字段完全没被修改。
向上转型为Parent类型后,编译器会严格按照引用的静态类型(Parent)来访问字段,所以会直接取父类的name字段值,输出Parent name。
验证补充
如果在第二种情况中,用子类引用访问字段,会得到子类自己的字段值:
Child c = new Child(); System.out.println(c.name); // 输出 Child name
如果想在子类中访问父类被隐藏的字段,可以用super关键字:
public class Child extends Parent { public String name; public int age; public Child() { this.name = "Child name"; this.age = 10; System.out.println(super.name); // 输出 Parent name } }
总结建议
字段隐藏是Java允许但不推荐的不良实践,会导致代码逻辑混淆。如果需要修改父类字段的取值,推荐:
- 直接在子类中修改继承的字段(第一种方式)
- 给父类添加setter方法,通过方法调用修改字段值(更符合面向对象封装原则)
内容的提问来源于stack exchange,提问作者Юрий Зайцев
相关产品推荐
相关产品推荐

