首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java 繼承與多態核心機制深度解析:構造鏈、不可變類與 toString 協議

     編輯:Java 綜合教學

繼承與多態:從構造器鏈到運行時多態的完整圖譜

繼承與多態是面向對象編程的基石。本文通過五個經典實例,系統梳理構造器調用鏈、不可變類設計、Object 協議、字符串連接多態、super 調用機制等核心知識點。

一、構造器調用鐵律: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 保證值語義

價值:天然線程安全,無需加鎖,性能優越,適合並發環境共享。

三、Object.toString() 協議與隱式調用

當對象與字符串進行 + 運算時,編譯器自動插入 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 調用

覆蓋要求:方法簽名(名稱、參數、返回類型)完全一致,否則為重載。

super 調用父類被覆蓋方法:

class Parent extends Grandparent {
    public Parent() {
        super("Hello.Grandparent"); // 調用父類帶參構造器
        System.out.println("Parent Created");
    }
}

此處 super(...) 調用的是 Grandparent(String),而非無參構造器,演示了構造器重載與繼承的協作。

五、探索 JDK 源碼:匿名類的默認 toString

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 實現(通常基於對象地址)。

總結

  1. 構造器鏈自下而上,super 必須首行,保證父類先初始化
  2. 不可變類:final 類 + final 字段 + 無 setter + 正確 equals/hashCode
  3. toString() 是對象字符串表示的標準協議,+ 運算隱式調用
  4. 方法覆蓋要求簽名完全一致,super.方法名() 可訪問父類實現

這些機制構成了 Java 面向對象運行時行為的核心骨架,深入理解它們是寫出健壯、可維護代碼的前提。

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