重寫 發生在父子類之間,體現運行時多態(動態分派);重載 發生在同一類內(或父子類),體現編譯時多態(靜態分派)。
| 維度 | 重寫 | 重載 |
|---|---|---|
| 發生位置 | 子類重寫父類方法 | 同一類中(或子類對父類方法重載) |
| 方法名 | 必須相同 | 必須相同 |
| 參數列表 | 必須完全相同 | 必須不同(類型/個數/順序) |
| 返回類型 | 必須相同或协变返回类型(Java 5+ 子類型) | 可以相同,可以不同 |
| 訪問修飾符 | 不能更低(public > protected > default > private) | 可任意修改 |
| 拋出異常 | 不能拋出新的或更寬的檢查異常 | 可拋出任意異常 |
| 靜態方法 | 不能重寫(隱藏) | 可重載 |
| final 方法 | 不能重寫 | 可重載 |
| private 方法 | 不能重寫(不可見) | 可重載(同類內) |
| 構造方法 | 不能重寫 | 可重載(同類多構造器) |
| 多態類型 | 運行時多態(動態綁定) | 編譯時多態(靜態綁定) |
class Animal {
public void move() { System.out.println("動物移動"); }
public Animal getSelf() { return this; }
}
class Dog extends Animal {
@Override
public void move() { System.out.println("狗跑"); } // 參數、返回類型相同
@Override
public Dog getSelf() { return this; } // 協變返回類型
}
class Calculator {
public int add(int a, int b) { return a + b; }
public double add(double a, double b) { return a + b; } // 參數類型不同
public int add(int a, int b, int c) { return a + b + c; } // 參數個數不同
public int add(int a, int b, int c, int d) { return a + b + c + d; }
}
子類重寫方法返回類型可以是父類返回類型的子類。實現「工廠方法」鏈式調用、Builder 模式鏈式返回 this。
class Parent { static void foo() { System.out.println("Parent"); } }
class Child extends Parent { static void foo() { System.out.println("Child"); } }
Parent p = new Child();
p.foo(); // 輸出 "Parent" —— 編譯期綁定 Parent.foo(),無動態分派
子類定義同名私有方法屬於新方法,與父類無關。若父類私有方法被子類調用(父類公共方法內部調用),仍執行父類版本。
重寫方法拋出異常必須是父類方法拋出異常的子類(或不拋出),保證調用端 catch (ParentException) 能捕獲所有子類實現拋出的異常,維護契約兼容性。
super() 初始化父類部分。@Override 註解? 必須加,編譯器驗證確實重寫,防止拼寫錯誤導致變為重載。invokevirtual 指令),實現「同一接口,不同實現」。invokestatic/invokespecial/invokevirtual),生成字節碼時已確定調用目標。清晰區分「重寫=繼承+多態」與「重載=同名+不同參數」,是掌握 Java 面向對象核心機制、通過面試、寫出正確代碼的基石。