一文詳解Java中三大異常處理方式(try-catch、throw、throws)
前言
這三種方式(try-catch、throw、throws)是 Java 異常處理的三大基石。要搞懂它們,最重要的是明白它們分別處于異常處理流程中的哪個環(huán)節(jié)。
1. try-catch:自己處理(捕獲與解決)
這是 Java 處理異常最直接的方式,用于在代碼內(nèi)部捕獲異常并進行處理,從而保證程序能繼續(xù)運行。
- 定義位置:方法體內(nèi)部。
- 結(jié)構(gòu)組成:由
try塊和一個或多個catch塊組成(還可以包含finally塊)。 - 執(zhí)行邏輯:
- try 塊:包裹可能拋出異常的代碼段。程序正常執(zhí)行時,逐行執(zhí)行 try 塊內(nèi)的代碼。
- 異常觸發(fā):如果 try 塊中的某行代碼拋出異常,try 塊中剩余的代碼將不再執(zhí)行,程序立即跳轉(zhuǎn)到與異常類型匹配的
catch塊。 - catch 塊:捕獲特定類型的異常對象。在 catch 塊中編寫處理該異常的邏輯(如日志記錄、恢復(fù)操作、提示用戶等)。如果沒有異常發(fā)生,catch 塊將被跳過。
- 作用:將異常處理邏輯與正常業(yè)務(wù)邏輯分離,防止因異常導(dǎo)致程序非正常終止。
語法詳解
try {
// 1. try 塊:放可能出現(xiàn)問題的代碼( risky code )
int result = 10 / 0; // 這里會拋出 ArithmeticException 異常
System.out.println("這行代碼不會執(zhí)行,因為上面出錯了");
} catch (ArithmeticException e) {
// 2. catch 塊:如果 try 里的代碼真的出錯了,就會跳到這里來執(zhí)行
System.out.println("哎呀,除數(shù)不能為0!補救措施:把除數(shù)改為1");
// e 就是捕獲到的那個異常對象,你可以用它打印錯誤信息
e.printStackTrace();
}
System.out.println("程序繼續(xù)運行...");
- 關(guān)鍵點:
- try:監(jiān)控代碼。
- catch:匹配異常類型(如
ArithmeticException)。如果 try 里拋出的異常和 catch 括號里的類型一致(或是其子類),就進入 catch 塊執(zhí)行。 - 執(zhí)行順序:一旦 try 中某行出錯,直接跳過 try 剩余代碼,進入對應(yīng)的 catch。
- 多重 catch:你可以寫多個
catch來處理不同的異常,就像準(zhǔn)備不同的急救包。
補充:
finally:最終執(zhí)行塊
- 定義:位于
try-catch結(jié)構(gòu)之后的代碼塊。 - 核心特性:無論
try塊中是否發(fā)生異常,也無論是否執(zhí)行了return語句,finally塊中的代碼一定會執(zhí)行。 - 主要作用:用于資源釋放。通常在代碼執(zhí)行完畢后,關(guān)閉文件流、數(shù)據(jù)庫連接或釋放鎖,確保不占用系統(tǒng)資源。
- 唯一例外:如果在
try或catch中執(zhí)行了System.exit(0)強制終止 JVM,或者發(fā)生了斷電宕機,finally才不會執(zhí)行。
2. throw:主動制造(拋出異常)
這是一個動作關(guān)鍵字,用于在代碼中顯式地生成并拋出一個異常對象。它不是“處理”異常,而是“制造”異常。
- 定義位置:方法體或代碼塊內(nèi)部。
- 操作對象:后面必須跟一個
Throwable類及其子類的實例化對象。 - 執(zhí)行邏輯:
- 程序執(zhí)行到
throw語句時,會立即停止當(dāng)前方法的后續(xù)代碼執(zhí)行。 - 它將創(chuàng)建的異常對象拋出給 Java 運行時系統(tǒng)。
- 如果該
throw語句未包裹在try-catch塊中,或者catch塊未捕獲該異常,則該方法將立即結(jié)束,并將異常拋給該方法的調(diào)用者。
- 程序執(zhí)行到
- 作用:通常用于業(yè)務(wù)邏輯校驗。當(dāng)程序狀態(tài)不符合預(yù)期(如參數(shù)非法、狀態(tài)錯誤)時,主動中斷流程并向上層報告錯誤。
語法詳解
public void checkAge(int age) {
// 邏輯判斷:如果年齡是負(fù)數(shù),這不符合邏輯
if (age < 0) {
// 主動創(chuàng)建一個異常對象,并用 throw 關(guān)鍵字拋出
// 就像你主動點燃了引信,扔出手雷
throw new IllegalArgumentException("年齡不能是負(fù)數(shù)!");
}
System.out.println("年齡檢查通過:" + age);
}
- 關(guān)鍵點:
throw寫在方法內(nèi)部。throw后面必須跟一個異常對象(new ...)。- 一旦執(zhí)行到
throw,當(dāng)前方法立即結(jié)束(就像遇到return一樣),后面的代碼不再執(zhí)行,控制權(quán)交給調(diào)用者。
3. throws:聲明推卸(聲明異常)
這是一個聲明關(guān)鍵字,用在方法簽名上。它表示當(dāng)前方法不處理某些異常,而是將異常的處理責(zé)任推給調(diào)用該方法的上層代碼。
- 定義位置:方法聲明中,參數(shù)列表之后,方法體之前。
- 操作對象:后面跟異常類名(可以多個,用逗號分隔),不是對象實例。
- 執(zhí)行邏輯:
- 聲明該方法在執(zhí)行過程中可能會拋出指定類型的異常。
- 當(dāng)調(diào)用者調(diào)用該方法時,編譯器會強制要求調(diào)用者必須處理這些聲明的異常(通過
try-catch捕獲,或者在自身的聲明中使用throws繼續(xù)向上拋出)。
- 作用:明確了方法的風(fēng)險邊界,實現(xiàn)了異常處理的傳遞(冒泡機制),讓方法的調(diào)用者決定如何處理底層發(fā)生的異常。
語法詳解
// 在方法定義時,使用 throws 關(guān)鍵字聲明可能拋出的異常列表
// 告訴調(diào)用者:調(diào)用我時,可能會遇到 FileNotFoundException,你自己看著辦!
public void readFile(String filePath) throws FileNotFoundException {
// 這里不需要 try-catch
// 如果文件真的找不到,JVM 會拋出 FileNotFoundException
// 這個異常會順著調(diào)用鏈,扔給調(diào)用 readFile 的人去處理
FileInputStream fis = new FileInputStream(filePath);
}
- 調(diào)用者怎么處理?
當(dāng)別人調(diào)用readFile方法時,編譯器會強制要求調(diào)用者處理這個異常(要么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("文件沒找到,我負(fù)責(zé)處理:新建一個文件");
}
}
- 關(guān)鍵點:
throws寫在方法聲明后面(括號外面)。- 后面跟的是異常類名(可以多個,用逗號隔開),不是對象。
- 它是一種**“甩鍋”**機制:將異常的處理責(zé)任轉(zhuǎn)移給上層調(diào)用者。
總結(jié)串聯(lián):它們是如何配合工作的?
讓我們把這三個關(guān)鍵詞串聯(lián)在一個完整的業(yè)務(wù)邏輯中:
假設(shè)我們有一個銀行轉(zhuǎn)賬的功能:
public class BankService {
// 1. throws 聲明:
// 這個方法告訴外界:“我可能會遇到錢不夠的情況,調(diào)用者要準(zhǔn)備好處理”
public void transfer(double amount) throws InsufficientFundsException {
if (amount < 0) {
// 2. throw 拋出:
// 程序員發(fā)現(xiàn)邏輯錯誤(轉(zhuǎn)賬金額為負(fù)),主動制造異常扔出去
throw new IllegalArgumentException("轉(zhuǎn)賬金額不能是負(fù)數(shù)!");
}
if (balance < amount) {
// 3. throw 拋出:
// 發(fā)現(xiàn)余額不足,主動制造一個“余額不足異?!比映鋈?
// 因為方法簽名上有 throws,這里可以直接扔,不用自己 catch
throw new InsufficientFundsException("余額不足,轉(zhuǎn)賬失敗");
}
// 正??劭钸壿?..
}
}
// 調(diào)用者
public class Main {
public void doTransfer() {
BankService bank = new BankService();
// 4. try-catch 捕獲:
// 因為 bank.transfer() 聲明了會扔出異常,所以這里必須接住
try {
bank.transfer(1000);
} catch (InsufficientFundsException e) {
// 處理余額不足的情況
System.out.println("提示用戶:充值");
} catch (IllegalArgumentException e) {
// 處理參數(shù)錯誤的情況
System.out.println("提示用戶:金額非法");
}
}
}
總結(jié)對比
| 關(guān)鍵字 | 類別 | 出現(xiàn)位置 | 核心作用 |
|---|---|---|---|
| try-catch | 處理機制 | 方法體內(nèi)部 | 攔截異常,就地解決,保證當(dāng)前流程不中斷。 |
| throw | 動作 | 方法體內(nèi)部 | 制造異常,顯式拋出一個異常對象,中斷當(dāng)前流程。 |
| throws | 聲明 | 方法簽名上 | 聲明異常,告知上層調(diào)用者這里可能出錯,需由調(diào)用者處理。 |
到此這篇關(guān)于Java中三大異常處理方式(try-catch、throw、throws)的文章就介紹到這了,更多相關(guān)Java異常處理try-catch、throw、throws內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot中SmartLifecycle的使用解析
這篇文章主要介紹了SpringBoot中SmartLifecycle的使用解析,SmartLifecycle是一個擴展了Lifecycle接口,可以跟蹤spring容器ApplicationContext刷新或者關(guān)閉的接口,實現(xiàn)該接口的實現(xiàn)類有特定的執(zhí)行順序,需要的朋友可以參考下2023-11-11
SpringBoot結(jié)合Redis配置工具類實現(xiàn)動態(tài)切換庫
本文主要介紹了SpringBoot結(jié)合Redis配置工具類實現(xiàn)動態(tài)切換庫,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08
使用WebUploader實現(xiàn)分片斷點上傳文件功能(二)
這篇文章主要為大家詳細(xì)介紹了使用WebUploader實現(xiàn)分片斷點上傳文件功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-01-01
SpringBoot項目配置logback-spring.xml屏蔽特定路徑的日志
在 Spring Boot 項目中,使用 logback-spring.xml 配置屏蔽特定路徑的日志有兩種常用方式,文中的示例代碼講解詳細(xì),有需要的小伙伴可以了解下2025-06-06
SpringBoot3集成Swagger3的詳細(xì)教程
Swagger 3(OpenAPI 3.0)提供了更加強大和靈活的API文檔生成能力,本教程將指導(dǎo)您如何在Spring Boot 3項目中集成Swagger3,并使用Knife4j作為UI界面,需要的朋友可以參考下2024-03-03

