Java中父子类同名成员变量是隐藏而非覆盖,因变量访问基于编译时类型静态绑定,而方法调用基于运行时类型动态绑定,故多态仅适用于方法不适用于变量。

Java 中父子类同名成员变量不会发生“覆盖”,而是各自独立存储在各自的对象内存空间中,这种现象叫成员变量的隐藏(Variable Hiding)。理解它关键在于区分编译时类型和运行时类型,以及变量访问的静态绑定机制。
为什么叫“隐藏”而不是“重写”
方法可以被重写(Override),但成员变量不能。当子类定义了与父类同名的实例变量时,子类的变量会隐藏父类中同名的变量——不是删除或替换,而是让父类变量在子类对象中依然存在,只是默认不可见。
例如:
class Parent {int value = 10;
}
class Child extends Parent {
int value = 20;
}
创建 Child c = new Child(); 后,内存中实际存在两个 value:一个属于 Parent 部分(值为 10),一个属于 Child 部分(值为 20)。它们占用不同偏移地址,互不干扰。
立即学习“Java免费学习笔记(深入)”;
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
访问哪个变量,取决于引用的声明类型
Java 编译器在编译阶段就根据引用变量的声明类型决定访问哪个同名变量,这是静态绑定,与实际对象类型无关。
-
Parent p = new Child(); System.out.println(p.value);→ 输出 10(看 p 是 Parent 类型) -
Child c = new Child(); System.out.println(c.value);→ 输出 20(c 是 Child 类型) -
System.out.println(((Parent)c).value);→ 输出 10(强制转为 Parent 类型后访问)
如何访问被隐藏的父类变量
在子类内部,可用 super.变量名 显式访问父类被隐藏的成员变量:
int value = 20;
void show() {
System.out.println(value); // 20(子类自己的)
System.out.println(super.value); // 10(父类的)
}
}
注意:super 只能在子类非静态上下文中使用,不能在静态方法或静态字段初始化中出现。
与方法重写的本质区别(重点对比)
变量隐藏是编译期行为;方法重写是运行期行为。这个差异直接体现为多态效果:
- 调用
p.method()(p 是 Parent 引用,指向 Child 实例)→ 执行的是Child.method()(动态绑定) - 访问
p.value→ 读取的是Parent.value(静态绑定)
所以,“多态”对变量不生效,只对非 private、非 static、非 final 的实例方法生效。

















