繼承與多態是面向對象編程的基石。本文通過五個經典實例,系統梳理構造器調用鏈、不可變類設計、Object 協議、字符串連接多態、super 調用機制等核心知識點。
規則:子類構造器執行前,必須顯式或隱式調用父類構造器。super(...) 若顯式調用,必須是構造器第一條語句。
class Grandparent {
public Grandparent() { System.out.println("GrandParent Created."); }
public Grandparent(String s) { System.out.println("GrandParent Created.String:" + s); }
}
class Parent extends Grandparent {
public Parent() {
super("Hello.Grandparent"); // 必須首行
System.out.println("Parent Created");
}
}
class Child extends Parent {
public Child() { System.out.println("Child Created"); }
}
public class TestInherit {
public static void main(String[] args) { new Child(); }
}
輸出順序:
GrandParent Created.String:Hello.Grandparent Parent Created Child Created
本質:繼承意味著子類建立在父類基礎之上,父類初始化必須先於子類完成。
public final class Address {
private final String detail;
private final String postCode;
public Address() { this("", ""); }
public Address(String detail, String postCode) {
this.detail = detail;
this.postCode = postCode;
}
// 僅提供 getter,無 setter
public String getDetail() { return detail; }
public String getPostCode() { return postCode; }
@Override public boolean equals(Object obj) {
if (obj instanceof Address) {
Address ad = (Address) obj;
return detail.equals(ad.detail) && postCode.equals(ad.postCode);
}
return false;
}
@Override public int hashCode() { return detail.hashCode() + postCode.hashCode(); }
}
核心要素:
final 修飾類(防繼承)、字段(保證引用不變)equals/hashCode 保證值語義價值:天然線程安全,無需加鎖,性能優越,適合並發環境共享。
當對象與字符串進行 + 運算時,編譯器自動插入 toString() 調用:
public class Fruit {
@Override public String toString() { return "Fruit toString."; }
public static void main(String[] args) {
Fruit f = new Fruit();
System.out.println("f=" + f); // 實際調用 "f=" + f.toString()
}
}
機制鏈:PrintStream.println(Object) → String.valueOf(Object) → Object.toString()。默認實現返回 類名@哈希碼,子類應重寫以提供業務含義。
覆蓋要求:方法簽名(名稱、參數、返回類型)完全一致,否則為重載。
super 調用父類被覆蓋方法:
class Parent extends Grandparent {
public Parent() {
super("Hello.Grandparent"); // 調用父類帶參構造器
System.out.println("Parent Created");
}
}
此處 super(...) 調用的是 Grandparent(String),而非無參構造器,演示了構造器重載與繼承的協作。
class A {} // 無任何成員
public class ExplorationJDKSource {
public static void main(String[] args) {
System.out.println(new A()); // 輸出類似 A@15db9742
}
}
驗證了 Object.toString() 默認實現:getClass().getName() + "@" + Integer.toHexString(hashCode())。hashCode() 為本地方法,由 JVM 實現(通常基於對象地址)。
super 必須首行,保證父類先初始化final 類 + final 字段 + 無 setter + 正確 equals/hashCodetoString() 是對象字符串表示的標準協議,+ 運算隱式調用super.方法名() 可訪問父類實現這些機制構成了 Java 面向對象運行時行為的核心骨架,深入理解它們是寫出健壯、可維護代碼的前提。