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

