贝利信息

Java 中子类与父类同名字段的隐藏机制详解

日期:2026-01-14 00:00 / 作者:霞舞

java 中子类声明与父类同名的实例字段时,并非覆盖父类字段,而是**隐藏(hiding)**它;同一对象内存中实际存在两个独立的 `x` 字段,分别属于父类和子类部分,通过 `this.x` 和 `super.x` 可明确访问。

在 Java 继承体系中,当子类 C 继承父类 P 并声明同名字段(如 int x)时,并不会发生字段覆盖(overriding)——因为字段不支持多态,而是触发 字段隐藏(field hiding) 机制。这是 Java 语言规范(JLS §8.3)明确定义的行为:子类中同名字段会隐藏所有可访问的父类同名字段。

关键在于:一个 C 类实例在内存中确实包含两份 x 字段——一份来自父类 P 的子对象结构(初始化于 P() 构造器),另一份来自子类 C 自身(初始化于 C() 构造器)。它们物理上独立存储,位于对象内存布局的不同偏移位置。

以下代码清晰展示了这一机制:

class P {
    int x;
    P() { x = 1; }
    public int getX() { return x; } // 访问的是 P.x(即 this.x 在 P

上下文中) } class C extends P { int x; // 隐藏了 P.x,但不删除它 C() { super(); // 隐式调用,初始化 P.x = 1 this.x = 2; // 初始化 C.x = 2 } void printBoth() { System.out.println("this.x (C.x): " + this.x); // 输出 2 System.out.println("super.x (P.x): " + super.x); // 输出 1 } }

运行结果:

this.x (C.x): 2
super.x (P.x): 1

回到原始示例中的输出差异:

⚠️ 注意事项:

总结:Java 对象是“组合式”的——new C() 创建的是一个逻辑上由 P 子对象和 C 扩展部分共同构成的单一对象,其字段空间是累加的。理解字段隐藏而非覆盖,是掌握 Java 继承内存模型的关键一步。