在 Java 物件導向程式設計中,繼承、多態、方法重載與重寫是四大核心支柱。它們不僅構成了類別之間關係的基石,更決定了程式碼的可擴展性與維護性。本文將系統梳理這四大概念的定義、實現機制、關鍵差異與最佳實踐,並輔以程式碼範例幫助深度理解。
繼承允許在現有類別(父類別/基類別)基礎上,透過新增方法或重新定義既有方法(即重寫)來建立新類別(子類別/衍生類別)。Java 中所有類別隱含繼承自 java.lang.Object,若未顯式指定 extends,編譯器會自動補上。
class 定義,無抽象方法。abstract class 定義,可含抽象方法。interface 定義,方法預設為 public abstract。繼承關鍵字規則:
| 子類型 | 繼承類別 | 繼承抽象類別 | 實作介面 |
|---|---|---|---|
| 具體類別 | extends | extends | implements |
| 抽象類別 | extends | extends | implements |
| 介面 | — | — | extends |
注意:extends 與 implements 不可互換。介面只能繼承介面,支援多重繼承;類別與抽象類別僅支援單一繼承(類別或抽象類別二擇一),但可實作多個介面。
繼承屬「is-a」關係(如「黃種人是人類」),組合屬「has-a」關係(如「汽車有引擎」)。若新類別與舊類別無包含關係,組合更佳,因能避免破壞封裝、降低耦合。組合範例:
public class Sub {
private Parent p = new Parent();
public void doSomething() {
p.method(); // 透過委派複用
}
}
兩種方式皆屬增量式開發,不修改原始碼,降低引入 Bug 風險,適合維護既有系統。
多態指「一種型別,多種行為」。同一介面(或父類別)引用指向不同子類別物件時,呼叫同一方法會呈現不同行為。其基礎是繼承,實現機制是後期綁定(動態綁定):執行期根據物件實際型別決定呼叫哪個方法版本。
static、final、private 方法。interface Car {
String getName();
int getPrice();
}
class BMW implements Car { ... }
class CheryQQ implements Car { ... }
class CarShop {
private int money = 0;
public void sellCar(Car car) { // 參數為介面型別
money += car.getPrice(); // 動態綁定,自動調用對應實作
}
}
新增車型只需實作 Car 介面,CarShop 完全無需修改,完美展現「開放封閉原則」。
方法簽名包含:方法名稱 + 參數列表(數量、型別、順序)。不包含回傳型別、存取修飾符、abstract/static/final 等關鍵字。
super() 呼叫父類別建構子。原文包含大量 C++ 範例,闡述「隱藏」與「覆蓋」的微妙差異。核心結論:
using Base::fun; 顯式引入。virtual 關鍵字決定是「覆蓋」(多態)還是「隱藏」:有 virtual 且簽名相同 → 覆蓋;無 virtual → 隱藏。String str = new String("abc"); // 建立幾個物件?
答案:2 個。"abc" 在字串池建立 1 個;new String(...) 在堆積建立第 2 個,str 指向堆積物件。
new String() 每次都在堆積建立新物件,不進池。intern() 可手動將堆積字串放入池中(若池中已有相同值則返回池中引用)。"ab" + "cd" → "abcd" 直接進池;含變數的連接則在執行期建立,不進池。char[] value)。@Override 註解,編譯器可攔截簽名錯誤。StringBuilder,避免無謂 new String()。掌握這四大核心概念,是寫出健壯、可擴展 Java 程式的關鍵。建議結合原始碼除錯、反編譯觀察字節碼,深化對 JVM 方法分派機制的理解。