java中属性不能被覆盖,只能被隐藏;字段访问由引用类型静态决定,而非动态绑定,父类与子类同名字段独立存储且共存于对象中。

字段隐藏不是覆盖,而是编译期静态绑定
当父类和子类定义了同名字段(无论访问修饰符或类型是否相同),子类字段不会覆盖父类字段,而是独立存在——两者共存于同一个对象实例中。访问哪个字段,取决于变量的声明类型,而不是实际运行时的对象类型。
- 例如:
Parent p = new Child();,用p.field访问的是Parent类中的字段 - 而
((Child)p).field或直接new Child().field访问的是Child类中声明的字段 - 即使字段名、类型、修饰符都一样,它们仍是两个独立存储空间
多层级继承下的字段隐藏表现
假设有三层:A → B → C,每层都声明了 int value:
-
A中value = 10 -
B中value = 20(隐藏 A 的) -
C中value = 30(隐藏 B 的,也间接隐藏 A 的)
此时一个 C 实例内存中实际包含三个独立的 value 字段(只要它们不是 private 且未被其他机制屏蔽)。但你无法通过 this.value 直接访问父类的,除非显式用 super.value(仅限直接父类)或强制转型。
如何安全地实现“类似覆盖”的语义
若你真正想要的是可被子类定制、支持多态访问的值,应避免直接暴露字段,改用以下方式:
-
用 protected 字段 + getter/setter 方法:让子类重写 getter,实现动态行为(如
getValue()返回不同值) -
所有字段设为 private,统一通过模板方法控制:父类定义
final getValue(),调用抽象doGetValue(),由子类实现 - 使用 final 字段 + 构造器注入:每个子类在构造时确定自己的值,不可变且清晰
特别注意 private 和访问权限的影响
private 字段虽不能被子类直接访问,但它仍被继承(存在于对象内存中),只是不可见。子类声明同名 private 字段,是完全独立的新字段,与父类无任何关系——连 super. 都无法访问父类的 private 字段。
而 protected 或包级字段被隐藏后,可通过 super.field 在子类内部访问父类版本(仅限直接父类),但外部代码仍按引用类型解析。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











