Java中方法重載與重寫的區(qū)別與避坑指南
引言
在 Java 基礎(chǔ)面試中,重載(Overload)和重寫(Override)是必考知識點(diǎn);在實(shí)際開發(fā)中,二者也是實(shí)現(xiàn)多態(tài)、代碼復(fù)用、業(yè)務(wù)擴(kuò)展的核心基礎(chǔ)。
但絕大多數(shù)同學(xué)只懂皮毛,分不清底層差異,經(jīng)常踩坑:把重載當(dāng)成重寫、靜態(tài)方法誤判重寫、協(xié)變返回混淆、參數(shù)匹配出錯、多態(tài)調(diào)用失效等問題層出不窮。
一、Java 兩大多態(tài)機(jī)制
想要徹底理解重載和重寫,首先要搞懂 Java 的兩種多態(tài),這是二者的本質(zhì)區(qū)別:
1. 靜態(tài)多態(tài)(編譯期多態(tài))
程序在編譯階段就已經(jīng)確定調(diào)用哪個方法,方法綁定不可更改,重載屬于靜態(tài)多態(tài)。
2. 動態(tài)多態(tài)(運(yùn)行期多態(tài))
程序在運(yùn)行階段根據(jù)對象的真實(shí)類型,動態(tài)綁定對應(yīng)方法,重寫屬于動態(tài)多態(tài),也是 Java 面向?qū)ο蟮暮诵奶匦浴?/p>
二、方法重載(Overload)完整詳解
1. 官方定義
方法重載:在同一個類中,存在多個方法名完全相同,但參數(shù)列表不同的方法,這種現(xiàn)象就是方法重載。
2. 觸發(fā)重載的三種條件(滿足其一即可)
參數(shù)列表不同,只包含以下三種情況,除此之外,所有條件都不參與重載判定:
- 參數(shù)個數(shù)不同
- 參數(shù)類型不同
- 參數(shù)順序不同(不同類型參數(shù)調(diào)換順序)
3. 合法重載代碼示例
public class OverloadDemo {
// 基礎(chǔ)方法
public void test(int a) {
System.out.println("參數(shù)為int類型");
}
// 重載1:參數(shù)個數(shù)不同
public void test(int a, int b) {}
// 重載2:參數(shù)類型不同
public void test(String a) {}
// 重載3:參數(shù)順序不同(不同類型)
public void test(int a, String b) {}
public void test(String b, int a) {}
}4. 重載判定的「四大無關(guān)項(xiàng)」
很多新手踩坑:返回值、訪問權(quán)限、方法異常、方法修飾符,完全不參與重載判斷!
僅靠這四項(xiàng)不同,無法構(gòu)成重載,直接編譯報錯!
// 錯誤示例:僅返回值不同,不構(gòu)成重載
public void demo(){}
public int demo(){ return 1; }
// 錯誤示例:僅權(quán)限不同,不構(gòu)成重載
public void func(){}
private void func(){}5. 重載底層原理
編譯階段,編譯器會根據(jù)方法名+參數(shù)列表生成唯一的方法簽名,區(qū)分不同重載方法。
簡單說:代碼寫完,編譯完成,調(diào)用哪個方法就已經(jīng)定死了,不存在運(yùn)行時變化,這就是靜態(tài)綁定。
三、方法重寫(Override)詳解
1. 官方定義
方法重寫:發(fā)生在父子類繼承關(guān)系中,子類對父類中非私有、非靜態(tài)、非final的實(shí)例方法進(jìn)行重新實(shí)現(xiàn),保持方法簽名一致,覆蓋父類原有邏輯,實(shí)現(xiàn)子類個性化業(yè)務(wù)。
2. 重寫五大硬性規(guī)則
1. 方法名、參數(shù)列表必須和父類完全一致
2. 權(quán)限修飾符:子類權(quán)限 ≥ 父類權(quán)限(只能放大,不能縮?。?/p>
3. 返回值:支持協(xié)變返回(引用類型可返回子類,基本類型必須一致)
4. 異常:子類拋出的受檢異常,不能比父類更寬泛
5. 禁止重寫的方法:private、static、final、構(gòu)造方法
3. 合法重寫代碼示例
class Person {}
class Student extends Person {}
class Father {
public Person getInfo() {
return new Person();
}
public void say() throws Exception {}
}
class Son extends Father {
// 合法:協(xié)變返回,返回子類類型
@Override
public Student getInfo() {
return new Student();
}
// 合法:子類異常范圍更小
@Override
public void say() throws RuntimeException {}
}4. 重寫底層原理
重寫基于動態(tài)綁定:編譯時看父類引用,運(yùn)行時看真實(shí)對象類型。
JVM 在運(yùn)行時通過**虛方法表(vtable)**找到子類重寫后的方法執(zhí)行,這也是多態(tài)的核心實(shí)現(xiàn)。
四、重載 & 重寫 終極對比表
對比維度 | 重載 Overload | 重寫 Override |
發(fā)生范圍 | 同一個類內(nèi)部 | 父子類繼承關(guān)系中 |
方法名 | 必須相同 | 必須相同 |
參數(shù)列表 | 必須不同 | 必須完全一致 |
返回值 | 無要求,不參與判定 | 基本類型一致,引用類型支持協(xié)變 |
權(quán)限修飾符 | 無要求 | 權(quán)限只能擴(kuò)大,不能縮小 |
異常拋出 | 無要求 | 受檢異常范圍只能更小或相同 |
綁定時機(jī) | 編譯期靜態(tài)綁定 | 運(yùn)行期動態(tài)綁定 |
多態(tài)類型 | 靜態(tài)多態(tài) | 動態(tài)多態(tài) |
注解支持 | 無專屬注解 | 必須加 @Override 校驗(yàn) |
五、注意事項(xiàng)
1:靜態(tài)方法「看似重寫,實(shí)則覆蓋」
核心結(jié)論:靜態(tài)方法不能重寫,只能覆蓋,多態(tài)完全失效!
class Father {
public static void show() {
System.out.println("父類靜態(tài)方法");
}
}
class Son extends Father {
public static void show() {
System.out.println("子類靜態(tài)方法");
}
}
// 測試調(diào)用
public class Test {
public static void main(String[] args) {
Father f = new Son();
f.show(); // 輸出:父類靜態(tài)方法
}
}原因:靜態(tài)方法屬于類,不屬于對象,編譯期綁定父類類型,和子類無關(guān),不存在多態(tài)。
2:參數(shù)類型不一致,誤把「重載」當(dāng)「重寫」
這是新手最高頻錯誤!參數(shù)細(xì)微不同,根本不是重寫,是重載!
class Father {
public void test(Object obj) {}
}
class Son extends Father {
// 不是重寫!是重載!參數(shù)類型不一致
public void test(String str) {}
}避坑方案:重寫必須加 @Override,編譯器自動校驗(yàn),杜絕此類問題。
3:private 方法不存在重寫
父類私有方法對子類不可見,子類同名方法是全新方法,和重寫無關(guān)。
class Father {
private void test() {
System.out.println("父類私有方法");
}
}
class Son extends Father {
public void test() {
System.out.println("子類方法");
}
}4:權(quán)限修飾符越改越小,編譯報錯
重寫規(guī)則:子類訪問權(quán)限不能比父類嚴(yán)格
權(quán)限等級:public > protected > 默認(rèn)包訪問權(quán)限 > private
5:受檢異常范圍擴(kuò)大,重寫失敗
運(yùn)行時異常無限制,受檢異常必須子類 ≤ 父類,不能拋出更大范圍異常。
6:可變參數(shù)與數(shù)組參數(shù)沖突,無法重載
可變參數(shù)本質(zhì)是數(shù)組,二者視為同一個方法,不構(gòu)成重載:
// 編譯報錯,沖突
public void fun(int[] arr){}
public void fun(int... arr){}7:僅參數(shù)名稱不同,不構(gòu)成重載
重載只看參數(shù)類型、個數(shù)、順序,參數(shù)名不參與判定。
六、@Override 注解的核心價值
很多人以為它是擺設(shè),其實(shí)是防坑神器:
1. 強(qiáng)制編譯器校驗(yàn)當(dāng)前方法是否為合法重寫
2. 杜絕參數(shù)寫錯、返回值錯誤、靜態(tài)覆蓋、權(quán)限錯誤等所有重寫問題
3. 提升代碼可讀性,一眼區(qū)分普通方法和重寫方法
開發(fā)規(guī)范:所有重寫方法,必須添加 @Override 注解!
七、總結(jié)
重載:同類、同名不同參、編譯綁定、靜態(tài)多態(tài),為了靈活適配多場景調(diào)用。
重寫:父子、同名同參、運(yùn)行綁定、動態(tài)多態(tài),為了子類個性化擴(kuò)展。
記住:重載看參數(shù),重寫看繼承;重載編譯定,重寫運(yùn)行變。
寫在最后
重載和重寫看似簡單,卻是 Java 面向?qū)ο?、多態(tài)機(jī)制的基石,也是面試和實(shí)際開發(fā)的高頻考點(diǎn)。很多高級特性(多態(tài)調(diào)用、框架底層封裝、方法擴(kuò)展)都建立在這兩個特性之上。
看似基礎(chǔ)的知識點(diǎn),往往最容易藏坑。基礎(chǔ)打牢,才能走得更遠(yuǎn),吃透這篇,徹底告別重載重寫相關(guān)bug和面試短板!
以上就是Java中方法重載與重寫的區(qū)別與避坑指南的詳細(xì)內(nèi)容,更多關(guān)于Java方法重載與重寫區(qū)別的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
基于String和List<String>間的相互轉(zhuǎn)換方式
這篇文章主要介紹了基于String和List間的相互轉(zhuǎn)換方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-05-05
SpringBoot實(shí)現(xiàn)郵件任務(wù)的步驟詳解
這篇文章主要介紹了SpringBoot實(shí)現(xiàn)郵件任務(wù)的步驟詳解,使用Spring Boot實(shí)現(xiàn)QQ郵箱發(fā)送郵件具有快速集成、統(tǒng)一的開發(fā)體驗(yàn)、強(qiáng)大的維護(hù)和擴(kuò)展能力、可靠的送達(dá)性和安全性等優(yōu)勢,可以幫助你快速構(gòu)建穩(wěn)定可靠的郵件發(fā)送功能,需要的朋友可以參考下2023-10-10
JAVA JNI原理詳細(xì)介紹及簡單實(shí)例代碼
這篇文章主要介紹了JAVA JNI原理的相關(guān)資料,這里提供簡單實(shí)例代碼,需要的朋友可以參考下2016-12-12
java中以DES的方式實(shí)現(xiàn)對稱加密并提供密鑰的實(shí)例
這篇文章主要介紹了java中以DES的方式實(shí)現(xiàn)對稱加密并提供密鑰的實(shí)例的相關(guān)資料,這里提供實(shí)例幫助大家學(xué)習(xí)理解這部分知識,需要的朋友可以參考下2017-08-08
SpringBoot深入分析運(yùn)行原理與功能實(shí)現(xiàn)
我們發(fā)現(xiàn)springBoot程序開發(fā)比spring程序編寫起來容易的多。配置簡潔,依賴關(guān)系簡單,啟動運(yùn)行容易。那么結(jié)下了我們我們就要思考一下入門程序中的這些功能是怎么實(shí)現(xiàn)的2022-09-09
Spring元注解@HttpExchange聲明式調(diào)用HTTP
這篇文章主要介紹了Spring元注解@HttpExchange聲明式調(diào)用HTTP,Spring?Framework6和Spring?Boot3引入了聲明式HTTP客戶端@HttpExchange,通過接口注解簡化REST?API調(diào)用,核心注解包括@GetExchange、@PostExchange等對應(yīng)HTTP方法,支持路徑參數(shù)和請求體,需要的朋友可以參考下2025-10-10

