Java方法重載與重寫之同名方法的雙面魔法(最新整理)
Java方法重載與重寫:同名方法的雙面魔法
各位道友們好!今天咱們來聊聊Java中兩個容易混淆的概念:方法重載(Overloading)和方法重寫(Overriding)。這倆兄弟長得像,但性格完全不同,就像呂洞賓的劍法——看似相似,實則各有千秋!
方法重載(Overloading):同門師兄弟的不同絕技
什么是方法重載?
方法重載就像是一個門派里的師兄弟,雖然名字相同(方法名相同),但各有各的獨門絕技(參數(shù)列表不同)。
class KungFuMaster {
// 基礎招式
public void attack() {
System.out.println("普通拳法!");
}
// 重載版本1:帶武器
public void attack(String weapon) {
System.out.println("使用" + weapon + "攻擊!");
}
// 重載版本2:帶武器和力量
public void attack(String weapon, int power) {
System.out.println("使用" + weapon + "發(fā)動" + power + "成功力!");
}
// 重載版本3:不同參數(shù)順序
public void attack(int power, String weapon) {
System.out.println(power + "成功力施展" + weapon + "!");
}
}重載的核心特征
必要條件:
- 方法名必須相同
- 參數(shù)列表必須不同(類型、數(shù)量、順序)
- 返回類型可以相同也可以不同
- 訪問修飾符可以不同
調用示例:
KungFuMaster master = new KungFuMaster();
master.attack(); // 普通拳法!
master.attack("寶劍"); // 使用寶劍攻擊!
master.attack("寶劍", 8); // 使用寶劍發(fā)動8成功力!
master.attack(8, "寶劍"); // 8成功力施展寶劍!
重載的優(yōu)點
- 提高代碼可讀性:相同功能的方法使用相同名字
- 簡化API設計:用戶只需要記住一個方法名
- 靈活性強:支持多種參數(shù)組合
重載的陷阱和反例
反例1:僅靠返回類型不同不能重載
class ErrorExample {
public void show() { }
public int show() { return 1; } // 編譯錯誤!
}
// 原因:編譯器無法區(qū)分調用哪個方法,只看方法名和參數(shù)列表
反例2:參數(shù)列表必須真正不同
class ErrorExample2 {
public void train(String student) { }
public void train(String master) { } // 編譯錯誤!
}
// 原因:參數(shù)名不同不算重載,要看參數(shù)類型
方法重寫(Overriding):子承父業(yè)的技藝傳承
什么是方法重寫?
方法重寫就像是兒子繼承父親的手藝,但青出于藍而勝于藍——方法簽名相同,但實現(xiàn)更優(yōu)秀。
// 父類:老拳師
class OldMaster {
public void secretMove() {
System.out.println("老式絕招:降龍十八掌");
}
public final void forbiddenMove() {
System.out.println("禁招:不得傳授");
}
}
// 子類:新拳師
class NewMaster extends OldMaster {
@Override
public void secretMove() {
System.out.println("新式絕招:升級版降龍十八掌");
}
// 不能重寫final方法
// @Override
// public void forbiddenMove() { } // 編譯錯誤!
}重寫的核心規(guī)則
必要條件:
- 方法名、參數(shù)列表、返回類型必須完全相同
- 子類方法訪問權限不能比父類更嚴格
- 不能重寫final、private、static方法
@Override注解的重要性:
class SmartMaster extends OldMaster {
@Override // 加上這個注解更安全
public void secretMove() {
System.out.println("智能絕招");
}
// 如果沒有@Override,拼寫錯誤不會被發(fā)現(xiàn)
public void secretmove() { // 本想重寫,但方法名寫錯了
System.out.println("這其實是個新方法,不是重寫!");
}
}重寫的優(yōu)點
- 實現(xiàn)多態(tài):運行時根據(jù)實際對象類型調用方法
- 擴展性強:子類可以改進或擴展父類行為
- 符合開閉原則:對擴展開放,對修改關閉
重載 vs 重寫:終極對決
對比表格
| 特性 | 方法重載 (Overloading) | 方法重寫 (Overriding) |
|---|---|---|
| 發(fā)生位置 | 同一個類中 | 父子類之間 |
| 方法簽名 | 必須不同 | 必須相同 |
| 返回類型 | 可以不同 | 必須相同或協(xié)變 |
| 訪問權限 | 可以不同 | 不能更嚴格 |
| 綁定時機 | 編譯時綁定 | 運行時綁定 |
| 多態(tài)性 | 不支持多態(tài) | 支持多態(tài) |
實際代碼對比
class Animal {
// 重載示例
public void eat() {
System.out.println("動物吃東西");
}
public void eat(String food) {
System.out.println("動物吃" + food);
}
// 可重寫的方法
public void sleep() {
System.out.println("動物睡覺");
}
}
class Dog extends Animal {
// 重寫父類方法
@Override
public void sleep() {
System.out.println("狗狗趴著睡覺");
}
// 重載:新增方法
public void eat(String food, int amount) {
System.out.println("狗狗吃" + amount + "份" + food);
}
}深入理解:協(xié)變返回類型
Java 5的新特性
協(xié)變返回類型允許重寫方法時返回父類方法返回類型的子類型:
class Fruit {
public Fruit getFruit() {
return new Fruit();
}
}
class Apple extends Fruit {
@Override
public Apple getFruit() { // 返回Apple而不是Fruit
return new Apple();
}
}反例:Java 5之前的問題
// Java 5之前的寫法(需要強制轉型)
class OldApple extends Fruit {
@Override
public Fruit getFruit() {
return new Apple(); // 返回Fruit類型
}
}
Apple apple = (Apple) new OldApple().getFruit(); // 需要強制轉型
// 原因:早期Java要求返回類型必須完全一致構造器重載:特殊的重載案例
構造器重載的特點
構造器重載是方法重載的特殊形式,用于以不同方式創(chuàng)建對象:
class MartialArtsSchool {
private String name;
private int studentCount;
// 默認構造器
public MartialArtsSchool() {
this("無名武館", 10);
}
// 重載構造器1
public MartialArtsSchool(String name) {
this(name, 20);
}
// 重載構造器2
public MartialArtsSchool(String name, int studentCount) {
this.name = name;
this.studentCount = studentCount;
}
}反例:構造器重載的常見錯誤
class ErrorSchool {
private String name;
public ErrorSchool() {
// 忘記初始化name
}
public ErrorSchool(String name) {
this(); // 調用無參構造器
this.name = name; // 但無參構造器沒初始化
}
}
// 原因:構造器鏈調用時要確保所有路徑都正確初始化重寫中的super關鍵字
調用父類實現(xiàn)
重寫時經(jīng)常需要調用父類的原始實現(xiàn):
class ImprovedMaster extends OldMaster {
@Override
public void secretMove() {
super.secretMove(); // 先調用父類方法
System.out.println("追加新招式:九陽神功");
}
}反例:錯誤使用super
class WrongMaster extends OldMaster {
@Override
public void secretMove() {
System.out.println("我的新招式");
super.secretMove(); // 順序可能不對
}
}
// 可能的問題:業(yè)務邏輯要求先執(zhí)行父類方法實戰(zhàn)案例:完整的武術系統(tǒng)
綜合運用重載和重寫
// 基礎武術類
class MartialArt {
protected String name;
public MartialArt(String name) {
this.name = name;
}
// 可重寫的方法
public void practice() {
System.out.println("練習" + name);
}
public void practice(int hours) {
System.out.println("練習" + name + hours + "小時");
}
}
// 具體武術類型
class TaiChi extends MartialArt {
public TaiChi() {
super("太極拳");
}
@Override
public void practice() {
System.out.println("以柔克剛:" + name);
}
// 重載:新增練習方式
public void practice(String style) {
System.out.println("練習" + style + "式" + name);
}
}
class ShaolinKungfu extends MartialArt {
public ShaolinKungfu() {
super("少林功夫");
}
@Override
public void practice() {
super.practice(); // 調用父類方法
System.out.println("追加:金鐘罩鐵布衫");
}
}使用示例
public class MartialArtsTest {
public static void main(String[] args) {
MartialArt[] arts = {
new TaiChi(),
new ShaolinKungfu()
};
for (MartialArt art : arts) {
art.practice(); // 多態(tài):調用實際類型的重寫方法
}
TaiChi taiChi = new TaiChi();
taiChi.practice(2); // 重載:練習太極拳2小時
taiChi.practice("陳式"); // 重載:練習陳式太極拳
}
}常見陷阱和最佳實踐
陷阱1:混淆重載和重寫
class ConfusionExample {
public void method(Object obj) {
System.out.println("Object版本");
}
public void method(String str) {
System.out.println("String版本");
}
}
ConfusionExample example = new ConfusionExample();
example.method(null); // 輸出:String版本
// 原因:重載解析選擇最具體的類型陷阱2:靜態(tài)方法的重寫誤解
class Parent {
public static void staticMethod() {
System.out.println("父類靜態(tài)方法");
}
}
class Child extends Parent {
public static void staticMethod() {
System.out.println("子類靜態(tài)方法");
}
}
Parent obj = new Child();
obj.staticMethod(); // 輸出:父類靜態(tài)方法(不是多態(tài)?。?
// 原因:靜態(tài)方法不支持重寫,只支持隱藏最佳實踐總結
- 使用@Override注解:避免拼寫錯誤,明確重寫意圖
- 遵循里氏替換原則:子類應該可以替換父類
- 謹慎使用重載:避免過于復雜的重載組合
- 保持一致性:重寫方法應該保持與父類相同的契約
- 文檔化:為重寫和重載方法提供清晰的文檔
記憶口訣
重載重寫要分清,同名方法各不同
重載同 class 參數(shù)異,編譯時分顯神通
重寫父子 signature 同,運行時分多態(tài)功
@Override 是護身符,拼寫錯誤無處藏
靜態(tài) final 不能改,private 方法不繼承
掌握這兩招絕技,Java 江湖任你闖!
記住這些訣竅,你就能在Java的江湖中游刃有余地使用重載和重寫了!下次再見,道友們!
到此這篇關于Java方法重載與重寫:同名方法的雙面魔法的文章就介紹到這了,更多相關Java方法重載與重寫內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Spring中@ExceptionHandler注解的使用方式
這篇文章主要介紹了Spring中@ExceptionHandler注解的使用方式,@ExceptionHandler注解我們一般是用來自定義異常的,可以認為它是一個異常攔截器(處理器),需要的朋友可以參考下2024-01-01
解決springboot3:mybatis-plus依賴錯誤:org.springframework.beans.fac
這篇文章主要介紹了解決springboot3:mybatis-plus依賴錯誤:org.springframework.beans.factory.UnsatisfiedDependencyException問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-07-07

