首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

再探 Java 基礎:throw 與 throws 異常拋出機制深度解析

     編輯:Java 相關知識

異常處理是 Java 健壯性的基石。throw 與 throws 雖只一字之差,但語義、位置、職責截然不同。本文通過對比實驗、源碼級分析、最佳實踐,徹底釐清兩者關係。

異常拋出三種方式

  1. JVM 自動拋出:邏輯錯誤(除零)、類型轉換失敗等觸發運行時異常
  2. throw 顯式拋出:代碼中主動創建並拋出異常對象
  3. throws 聲明拋出:方法簽名聲明可能拋出的受檢異常

實驗驗證

1. JVM 自動拋出

// 除零
int a = 5, b = 0; System.out.println(a / b); 
// ArithmeticException: / by zero

// 類型轉換
String s = "abc"; Double.parseDouble(s); 
// NumberFormatException: For input string: "abc"

2. throw 顯式拋出

public static void main(String[] args) {
    String s = "abc";
    if (s.equals("abc")) {
        throw new NumberFormatException("業務邏輯禁止 abc");
    }
}
// NumberFormatException: 業務邏輯禁止 abc

3. throws 聲明拋出

public static void risky() throws NumberFormatException {
    Double.parseDouble("abc"); // 內部拋出,不捕獲,聲明拋出
}

public static void main(String[] args) {
    try { risky(); } 
    catch (NumberFormatException e) { System.err.println("非數據類型"); }
}
// 輸出:非數據類型

throw vs throws 核心對比

維度throwthrows
出現位置方法體內部語句方法聲明簽名
語義實際拋出異常對象聲明可能拋出的異常類型
確定性執行必拋出運行時不一定發生
異常數量單個對象可聲明多個,逗號分隔
處理責任當前方法或調用鏈強制調用者處理(受檢異常)
配合關係方法內 throw 後建議聲明 throws配合 try-catch 實現傳播

異常捕獲機制

try {
    // 風險代碼
} catch (ExceptionType e) {
    // 處理邏輯:記錄日誌、恢復、轉換異常、拋出
} finally {
    // 清理資源:關流、釋放鎖、關連接
}

關鍵行為

  • try 塊中異常發生後,後續語句不再執行,直接跳轉匹配的 catch
  • catch 參數類型必須是 Throwable 子類,多 catch 子類在前父類在後
  • finally 必定執行(System.exit、JVM crash 除外),即使 catch 中 return/throw

良好編程習慣

  1. 風險代碼入 try:主動包裹可能失敗的操作(IO、解析、網絡、反射)
  2. catch 必處理:至少 e.printStackTrace() 或日誌記錄,嚴禁空 catch
  3. IO 資源進 finally:流、連接、鎖在 finally 中關閉/釋放
  4. throw 伴隨 throws:方法內顯式 throw 後,方法簽名聲明 throws,語義清晰
  5. 自定義異常四步走:繼承 Exception → 構造方法 → throw 拋出 → 調用處 catch/throws

自定義異常示例

// 1. 定義
class DivideByZeroException extends Exception {
    public DivideByZeroException(String msg) { super(msg); }
}

// 2. 業務拋出
class Calculator {
    public int div(int a, int b) throws DivideByZeroException {
        if (b == 0) throw new DivideByZeroException("除數不能為零");
        return a / b;
    }
}

// 3. 調用處理
public static void main(String[] args) {
    try { System.out.println(new Calculator().div(10, 0)); }
    catch (DivideByZeroException e) { 
        System.err.println(e.getMessage()); // 除數不能為零
        e.printStackTrace();
    }
}

受檢 vs 非受檢異常選擇指南

  • 受檢異常 (Exception 子類非 RuntimeException):可預期、可恢復、調用者必須處理(如 IO 錯誤、數據庫連接失敗)
  • 非受檢異常 (RuntimeException 子類):編程錯誤、不可恢復、不強制處理(如空指針、索引越界、非法參數)

總結

throw 是動作,throws 是契約。異常機制將錯誤處理從業務邏輯中分離,構建「正常流」與「異常流」雙軌制。掌握兩者協作,配合 finally 資源管理、自定義異常語義化,是寫出專業級 Java 代碼的必修課。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved