贝利信息

Java 中父子类同名字段的隐藏机制与对象内存布局解析

日期:2026-01-14 00:00 / 作者:心靈之曲

java 子类声明与父类同名字段时,并非覆盖,而是**字段隐藏(field hiding)**:子类对象在内存中实际包含两份独立的 `x` 字段(`parent.x` 和 `child.x`),分别由各自构造器初始化,通过 `this.x` 和 `super.x` 可明确访问不同副本。

在 Java 中,当子类 C 继承父类 P 并定义了同名字段(如 int x;),这并非“重写”或“覆盖”,而是一种明确的语言特性——字段隐藏(Field Hiding),由《Java 语言规范》(JLS §8.3)明确定义:子类中同名字段会隐藏所有可访问的父类同名字段。关键在于:隐藏 ≠ 合并,它导致同一个对象实例中物理存在两个独立的 x 字段,分别隶属于父类和子类的继承层级。

内存结构:一个对象,两份字段

虽然 new C() 只创建一个对象实例,但该实例的内存布局包含:

二者在内存中是完全独立的变量,占据不同偏移地址,互不干扰。

访问规则决定输出差异

你观察到的输出:

c.x: 2
c.getX(): 1

正是字段隐藏行为的直接体现:

✅ 正确访问双字段的示例:

class Child extends Parent {
    int x;

    Child() {
        super(); // 显式调用父构造器(可省略,但强调执行顺序)
        this.x = 2;   // 初始化 C

hild.x } void printBothXs() { System.out.println("this.x (Child.x): " + this.x); // 输出 2 System.out.println("super.x (Parent.x): " + super.x); // 输出 1 } }

重要注意事项

总结来说,Java 的字段隐藏机制让单个对象能安全容纳多份同名字段,提升继承灵活性,但也要求开发者清晰区分 this. 与 super. 的语义边界——这不是 bug,而是 JLS 精心设计的、可预测的语言特性。