多態是面向對象編程三大特性之一,讓代碼具備極強的擴展性與復用性。本文通過實戰案例,層層遞進剖析 Java 多態的判斷、轉型規則、字段隱藏、方法重寫、字節碼實現原理,以及實際項目中的重構演示,助您徹底掌握多態精髓。
使用 instanceof 運算符可判斷對象是否為指定類型的實例。編譯類型決定調用哪些方法,運行時類型決定實際執行邏輯。例如:
Object hello = "Hello"; System.out.println(hello instanceof Object); // true System.out.println(hello instanceof String); // true System.out.println(hello instanceof Math); // false System.out.println(hello instanceof Comparable); // true (String 實現了 Comparable)
轉型規則: 父類引用指向子類對象時,向上轉型自動發生;向下轉型需強制轉換,且必須確保對象實際類型匹配,否則拋出 ClassCastException。
class Mammal {} class Dog extends Mammal {} class Cat extends Mammal {}
Mammal m; Dog d = new Dog(); Cat c = new Cat();
m = d; // 正確:向上轉型
// d = m; // 編譯錯誤:需強轉
d = (Dog)m; // 運行時正確:m 實際指向 Dog
// d = c; // 編譯錯誤:兄弟類無法轉換
// c = (Cat)m; // 運行時 ClassCastException:m 實際是 Dog
結論: 編譯器只檢查繼承關係,運行時檢查實際對象類型。
class Parent { public int myValue = 100; public void printValue() { System.out.println("Parent: " + myValue); } }
class Child extends Parent { public int myValue = 200; public void printValue() { System.out.println("Child: " + myValue); } }
Parent parent = new Child();
parent.printValue(); // 輸出 "Child: 200" —— 動態分派,調用子類方法
System.out.println(parent.myValue); // 輸出 100 —— 靜態綁定,訪問父類字段
((Child)parent).myValue++; // 修改子類字段
parent.printValue(); // 輸出 "Child: 201"
核心差異:
super.field 訪問父類字段。通過 javap -c TestPolymorphism.class 查看字節碼可見:方法調用指令為 invokevirtual。JVM 在運行時通過對象頭的類指针找到方法表,根據方法簽名查找實際實現,實現動態分派。這就是為什麼父類引用調用子類重寫方法會執行子類邏輯的底層原因。
版本 1(無多態): Feeder 類為每種動物單獨寫餵養方法,擴展新動物需修改 Feeder,違反開閉原則。
版本 2(引入繼承多態): 抽象 Animal 類定義 eat(),Feeder 僅需 feedAnimal(Animal a)。新增動物只需繼承 Animal,Feeder 零修改。
版本 3(數組批量處理): feedAnimals(Animal[]) 統一處理集合。
版本 4(集合容器): 使用 Vector<Animal> 進一步解耦。
總結: 多態讓系統在需求變更時「修改點最小、影響範圍最小」。兩大形式:繼承多態、接口多態。
定義抽象 PATM 類聲明業務操作,ATM 實現具體邏輯,PersonalAccount 封裝賬戶數據。主程序通過菜單驅動,展示多態在業務建模中的應用:統一接口、多態調用、擴展新業務(如理財、貸款)無需動核心流程代碼。
@Override 註解,編譯期捕獲簽名錯誤。多態不僅是語法糖,更是應對復雜業務變化的架構利器。深入理解其底層機制,能助您設計出更靈活、可維護的 Java 系統。