一文詳解Java中三大異常處理方式(try-catch、throw、throws)
前言
這三種方式(try-catch、throw、throws)是 Java 異常處理的三大基石。要搞懂它們,最重要的是明白它們分別處于異常處理流程中的哪個(gè)環(huán)節(jié)。
1. try-catch:自己處理(捕獲與解決)
這是 Java 處理異常最直接的方式,用于在代碼內(nèi)部捕獲異常并進(jìn)行處理,從而保證程序能繼續(xù)運(yùn)行。
- 定義位置:方法體內(nèi)部。
- 結(jié)構(gòu)組成:由
try塊和一個(gè)或多個(gè)catch塊組成(還可以包含finally塊)。 - 執(zhí)行邏輯:
- try 塊:包裹可能拋出異常的代碼段。程序正常執(zhí)行時(shí),逐行執(zhí)行 try 塊內(nèi)的代碼。
- 異常觸發(fā):如果 try 塊中的某行代碼拋出異常,try 塊中剩余的代碼將不再執(zhí)行,程序立即跳轉(zhuǎn)到與異常類型匹配的
catch塊。 - catch 塊:捕獲特定類型的異常對(duì)象。在 catch 塊中編寫處理該異常的邏輯(如日志記錄、恢復(fù)操作、提示用戶等)。如果沒(méi)有異常發(fā)生,catch 塊將被跳過(guò)。
- 作用:將異常處理邏輯與正常業(yè)務(wù)邏輯分離,防止因異常導(dǎo)致程序非正常終止。
語(yǔ)法詳解
try {
// 1. try 塊:放可能出現(xiàn)問(wèn)題的代碼( risky code )
int result = 10 / 0; // 這里會(huì)拋出 ArithmeticException 異常
System.out.println("這行代碼不會(huì)執(zhí)行,因?yàn)樯厦娉鲥e(cuò)了");
} catch (ArithmeticException e) {
// 2. catch 塊:如果 try 里的代碼真的出錯(cuò)了,就會(huì)跳到這里來(lái)執(zhí)行
System.out.println("哎呀,除數(shù)不能為0!補(bǔ)救措施:把除數(shù)改為1");
// e 就是捕獲到的那個(gè)異常對(duì)象,你可以用它打印錯(cuò)誤信息
e.printStackTrace();
}
System.out.println("程序繼續(xù)運(yùn)行...");
- 關(guān)鍵點(diǎn):
- try:監(jiān)控代碼。
- catch:匹配異常類型(如
ArithmeticException)。如果 try 里拋出的異常和 catch 括號(hào)里的類型一致(或是其子類),就進(jìn)入 catch 塊執(zhí)行。 - 執(zhí)行順序:一旦 try 中某行出錯(cuò),直接跳過(guò) try 剩余代碼,進(jìn)入對(duì)應(yīng)的 catch。
- 多重 catch:你可以寫多個(gè)
catch來(lái)處理不同的異常,就像準(zhǔn)備不同的急救包。
補(bǔ)充:
finally:最終執(zhí)行塊
- 定義:位于
try-catch結(jié)構(gòu)之后的代碼塊。 - 核心特性:無(wú)論
try塊中是否發(fā)生異常,也無(wú)論是否執(zhí)行了return語(yǔ)句,finally塊中的代碼一定會(huì)執(zhí)行。 - 主要作用:用于資源釋放。通常在代碼執(zhí)行完畢后,關(guān)閉文件流、數(shù)據(jù)庫(kù)連接或釋放鎖,確保不占用系統(tǒng)資源。
- 唯一例外:如果在
try或catch中執(zhí)行了System.exit(0)強(qiáng)制終止 JVM,或者發(fā)生了斷電宕機(jī),finally才不會(huì)執(zhí)行。
2. throw:主動(dòng)制造(拋出異常)
這是一個(gè)動(dòng)作關(guān)鍵字,用于在代碼中顯式地生成并拋出一個(gè)異常對(duì)象。它不是“處理”異常,而是“制造”異常。
- 定義位置:方法體或代碼塊內(nèi)部。
- 操作對(duì)象:后面必須跟一個(gè)
Throwable類及其子類的實(shí)例化對(duì)象。 - 執(zhí)行邏輯:
- 程序執(zhí)行到
throw語(yǔ)句時(shí),會(huì)立即停止當(dāng)前方法的后續(xù)代碼執(zhí)行。 - 它將創(chuàng)建的異常對(duì)象拋出給 Java 運(yùn)行時(shí)系統(tǒng)。
- 如果該
throw語(yǔ)句未包裹在try-catch塊中,或者catch塊未捕獲該異常,則該方法將立即結(jié)束,并將異常拋給該方法的調(diào)用者。
- 程序執(zhí)行到
- 作用:通常用于業(yè)務(wù)邏輯校驗(yàn)。當(dāng)程序狀態(tài)不符合預(yù)期(如參數(shù)非法、狀態(tài)錯(cuò)誤)時(shí),主動(dòng)中斷流程并向上層報(bào)告錯(cuò)誤。
語(yǔ)法詳解
public void checkAge(int age) {
// 邏輯判斷:如果年齡是負(fù)數(shù),這不符合邏輯
if (age < 0) {
// 主動(dòng)創(chuàng)建一個(gè)異常對(duì)象,并用 throw 關(guān)鍵字拋出
// 就像你主動(dòng)點(diǎn)燃了引信,扔出手雷
throw new IllegalArgumentException("年齡不能是負(fù)數(shù)!");
}
System.out.println("年齡檢查通過(guò):" + age);
}
- 關(guān)鍵點(diǎn):
throw寫在方法內(nèi)部。throw后面必須跟一個(gè)異常對(duì)象(new ...)。- 一旦執(zhí)行到
throw,當(dāng)前方法立即結(jié)束(就像遇到return一樣),后面的代碼不再執(zhí)行,控制權(quán)交給調(diào)用者。
3. throws:聲明推卸(聲明異常)
這是一個(gè)聲明關(guān)鍵字,用在方法簽名上。它表示當(dāng)前方法不處理某些異常,而是將異常的處理責(zé)任推給調(diào)用該方法的上層代碼。
- 定義位置:方法聲明中,參數(shù)列表之后,方法體之前。
- 操作對(duì)象:后面跟異常類名(可以多個(gè),用逗號(hào)分隔),不是對(duì)象實(shí)例。
- 執(zhí)行邏輯:
- 聲明該方法在執(zhí)行過(guò)程中可能會(huì)拋出指定類型的異常。
- 當(dāng)調(diào)用者調(diào)用該方法時(shí),編譯器會(huì)強(qiáng)制要求調(diào)用者必須處理這些聲明的異常(通過(guò)
try-catch捕獲,或者在自身的聲明中使用throws繼續(xù)向上拋出)。
- 作用:明確了方法的風(fēng)險(xiǎn)邊界,實(shí)現(xiàn)了異常處理的傳遞(冒泡機(jī)制),讓方法的調(diào)用者決定如何處理底層發(fā)生的異常。
語(yǔ)法詳解
// 在方法定義時(shí),使用 throws 關(guān)鍵字聲明可能拋出的異常列表
// 告訴調(diào)用者:調(diào)用我時(shí),可能會(huì)遇到 FileNotFoundException,你自己看著辦!
public void readFile(String filePath) throws FileNotFoundException {
// 這里不需要 try-catch
// 如果文件真的找不到,JVM 會(huì)拋出 FileNotFoundException
// 這個(gè)異常會(huì)順著調(diào)用鏈,扔給調(diào)用 readFile 的人去處理
FileInputStream fis = new FileInputStream(filePath);
}
- 調(diào)用者怎么處理?
當(dāng)別人調(diào)用readFile方法時(shí),編譯器會(huì)強(qiáng)制要求調(diào)用者處理這個(gè)異常(要么try-catch接住,要么繼續(xù)throws往上甩)。
public static void main(String[] args) {
try {
// 調(diào)用者必須用 try-catch 包裹,或者 main 方法也 throws
readFile("test.txt");
} catch (FileNotFoundException e) {
System.out.println("文件沒(méi)找到,我負(fù)責(zé)處理:新建一個(gè)文件");
}
}
- 關(guān)鍵點(diǎn):
throws寫在方法聲明后面(括號(hào)外面)。- 后面跟的是異常類名(可以多個(gè),用逗號(hào)隔開),不是對(duì)象。
- 它是一種**“甩鍋”**機(jī)制:將異常的處理責(zé)任轉(zhuǎn)移給上層調(diào)用者。
總結(jié)串聯(lián):它們是如何配合工作的?
讓我們把這三個(gè)關(guān)鍵詞串聯(lián)在一個(gè)完整的業(yè)務(wù)邏輯中:
假設(shè)我們有一個(gè)銀行轉(zhuǎn)賬的功能:
public class BankService {
// 1. throws 聲明:
// 這個(gè)方法告訴外界:“我可能會(huì)遇到錢不夠的情況,調(diào)用者要準(zhǔn)備好處理”
public void transfer(double amount) throws InsufficientFundsException {
if (amount < 0) {
// 2. throw 拋出:
// 程序員發(fā)現(xiàn)邏輯錯(cuò)誤(轉(zhuǎn)賬金額為負(fù)),主動(dòng)制造異常扔出去
throw new IllegalArgumentException("轉(zhuǎn)賬金額不能是負(fù)數(shù)!");
}
if (balance < amount) {
// 3. throw 拋出:
// 發(fā)現(xiàn)余額不足,主動(dòng)制造一個(gè)“余額不足異?!比映鋈?
// 因?yàn)榉椒ê灻嫌?throws,這里可以直接扔,不用自己 catch
throw new InsufficientFundsException("余額不足,轉(zhuǎn)賬失敗");
}
// 正??劭钸壿?..
}
}
// 調(diào)用者
public class Main {
public void doTransfer() {
BankService bank = new BankService();
// 4. try-catch 捕獲:
// 因?yàn)?bank.transfer() 聲明了會(huì)扔出異常,所以這里必須接住
try {
bank.transfer(1000);
} catch (InsufficientFundsException e) {
// 處理余額不足的情況
System.out.println("提示用戶:充值");
} catch (IllegalArgumentException e) {
// 處理參數(shù)錯(cuò)誤的情況
System.out.println("提示用戶:金額非法");
}
}
}
總結(jié)對(duì)比
| 關(guān)鍵字 | 類別 | 出現(xiàn)位置 | 核心作用 |
|---|---|---|---|
| try-catch | 處理機(jī)制 | 方法體內(nèi)部 | 攔截異常,就地解決,保證當(dāng)前流程不中斷。 |
| throw | 動(dòng)作 | 方法體內(nèi)部 | 制造異常,顯式拋出一個(gè)異常對(duì)象,中斷當(dāng)前流程。 |
| throws | 聲明 | 方法簽名上 | 聲明異常,告知上層調(diào)用者這里可能出錯(cuò),需由調(diào)用者處理。 |
到此這篇關(guān)于Java中三大異常處理方式(try-catch、throw、throws)的文章就介紹到這了,更多相關(guān)Java異常處理try-catch、throw、throws內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring?Cloud?Gateway動(dòng)態(tài)路由Apollo實(shí)現(xiàn)詳解
這篇文章主要為大家介紹了Spring?Cloud?Gateway動(dòng)態(tài)路由通過(guò)Apollo實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10
SpringSecurity?默認(rèn)登錄認(rèn)證的實(shí)現(xiàn)原理解析
這篇文章主要介紹了SpringSecurity?默認(rèn)登錄認(rèn)證的實(shí)現(xiàn)原理解析,本文通過(guò)圖文示例相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-12-12
Spring?Boot項(xiàng)目中遇到`if-else`語(yǔ)句七種具體使用方法解析
當(dāng)在Spring?Boot項(xiàng)目中遇到大量if-else語(yǔ)句時(shí),優(yōu)化這些代碼變得尤為重要,因?yàn)樗鼈儾粌H增加了維護(hù)難度,還可能影響應(yīng)用程序的可讀性和性能,以下是七種具體的方法,用于在Spring?Boot項(xiàng)目中優(yōu)化和重構(gòu)if-else語(yǔ)句,感興趣的朋友一起看看吧2024-07-07
詳解在Spring3中使用注解(@Scheduled)創(chuàng)建計(jì)劃任務(wù)
本篇文章主要介紹了詳解在Spring3中使用注解(@Scheduled)創(chuàng)建計(jì)劃任務(wù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-03-03
基于SpringBoot實(shí)現(xiàn)抽獎(jiǎng)活動(dòng)的四種策略
抽獎(jiǎng)活動(dòng)是產(chǎn)品運(yùn)營(yíng)中常見(jiàn)的用戶激勵(lì)和互動(dòng)手段,通過(guò)隨機(jī)性和獎(jiǎng)勵(lì)刺激用戶參與度,提升用戶活躍度和留存率,在技術(shù)實(shí)現(xiàn)上,抽獎(jiǎng)系統(tǒng)涉及到隨機(jī)算法、獎(jiǎng)品分配、防作弊機(jī)制等多方面內(nèi)容,本文將介紹基于SpringBoot實(shí)現(xiàn)抽獎(jiǎng)活動(dòng)的5種策略,需要的朋友可以參考下2025-06-06
java中的instanceof關(guān)鍵字詳細(xì)解讀
這篇文章主要介紹了java中的instanceof關(guān)鍵字詳細(xì)解讀,instanceof 是 Java 的保留關(guān)鍵字,它的作用是測(cè)試它左邊的對(duì)象是否是它右邊的類的實(shí)例,返回 boolean 的數(shù)據(jù)類型,需要的朋友可以參考下2024-01-01
SpringBoot整合RedisTemplate實(shí)現(xiàn)緩存信息監(jiān)控的基本操作
SpringBoot中的 redistemplate 是一個(gè)用于操作 Redis 數(shù)據(jù)庫(kù)的高級(jí)模板類,它提供了一組方法,可以方便地執(zhí)行常見(jiàn)的 Redis 操作,如存儲(chǔ)、檢索和刪除數(shù)據(jù),本文給大家介紹了SpringBoot整合RedisTemplate實(shí)現(xiàn)緩存信息監(jiān)控的基本操作,需要的朋友可以參考下2025-02-02

