首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

Java 繼承中字段隱藏與方法重寫的區別:為什麼輸出父類字段值?

     編輯:程式設計疑難解答

子類定義與父類同名字段時,字段不參與多態,調用父類繼承的方法訪問的是父類字段。本文通過代碼演示這一核心機制。

現象代碼

class Fu { int x = 7; void a() { System.out.println(this.x); } }
class Zi extends Fu { int x = 6; }
public class Test { public static void main(String[] args) { new Zi().a(); } }
// 輸出:7  (而非 6)

核心原因

  1. 字段隱藏:Zi.x 隱藏了 Fu.x,實際上 Zi 對象內存中有兩個 x:Fu.x=7 和 Zi.x=6。
  2. 方法不重寫:Zi 未重寫 a(),調用的是 Fu.a()。
  3. 編譯期綁定:Fu.a() 中的 this.x 在編譯期綁定為 Fu.x(聲明類型為 Fu)。

內存佈局圖解

Zi 對象內存:
+------------------+
| Fu 部分          |
|   x = 7    ← Fu.a() 訪問此處 |
+------------------+
| Zi 部分          |
|   x = 6    ← Zi 實例直接訪問此處 |
+------------------+

三種修正方案

1. 重寫方法(推薦)

class Zi extends Fu {
    int x = 6;
    @Override void a() { System.out.println(this.x); } // 訪問 Zi.x → 輸出 6
}

2. 子類構造器修改父類字段

class Zi extends Fu {
    Zi() { this.x = 6; } // 修改 Fu.x
    // 不聲明新 x
}

3. 使用 Getter 方法實現多態


class Fu {
    private int x = 7;
    public int getX() { return x; }
    void a() { System.out.println(getX()); } // 動態綁定
}
class Zi extends Fu {
    private int x = 6;
    @Override public int getX() { return x; }
}
// new Zi().a() → 輸出 6

總結對比

特性字段方法
多態性無(靜態綁定)有(動態綁定)
同名機制隱藏重寫
訪問方式編譯期看引用類型運行期看對象類型
最佳實踐私有化 + Getter/Setter@Override 註解

理解「字段隱藏 ≠ 方法重寫」,避免在繼承體系中直接暴露字段,是寫出健壯 Java 代碼的基礎。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved