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

Java 異常處理機制完整指南:try-catch-finally、throws、異常體系與最佳實踐

     編輯:Java 相關知識

異常體系架構


Throwable
├── Error (嚴重錯誤,程序無法恢復)
│   ├── OutOfMemoryError
│   ├── StackOverflowError
│   └── NoClassDefFoundError
└── Exception (可恢復異常)
    ├── RuntimeException (非受檢異常,編譯器不強制處理)
    │   ├── NullPointerException
    │   ├── IllegalArgumentException
    │   └── ArithmeticException
    └── 受檢異常 (編譯器強制 try-catch 或 throws)
        ├── IOException
        ├── SQLException
        └── ClassNotFoundException

核心捕獲語法

1. try-catch 基礎


public class ExceptionDemo {
    public static int divide(int a, int b) {
        return a / b; // 可能拋出 ArithmeticException
    }
    
    public static void main(String[] args) {
        try {
            int result = divide(5, 0); // 異常拋出點
            System.out.println("Result: " + result); // 不會執行
        } catch (ArithmeticException e) {
            e.printStackTrace(); // 打印堆疊追蹤
            System.out.println("捕獲除零異常: " + e.getMessage());
        }
        System.out.println("程序繼續執行..."); // 正常繼續
    }
}

關鍵點:異常拋出後,當前方法剩餘代碼**不再執行**,直接跳轉到匹配的 catch 塊。

2. finally 塊:必執行保障


try {
    riskyOperation();
    return "success";
} catch (Exception e) {
    log.error("失敗", e);
    return "error";
} finally {
    cleanup(); // 無論有無異常、有無 return,都會執行
}

唯一不執行情況:System.exit()、JVM 崩潰、無限循環/死鎖在 try/catch 中。

3. 多 catch 排序規則:子類在前,父類在後


// 錯誤:編譯失敗,ArithmeticException 被 Exception 遮蔽
try { ... }
catch (Exception e) { ... }
catch (ArithmeticException e) { ... }

// 正確:具體異常優先
try { ... }
catch (ArithmeticException e) { ... }
catch (IOException e) { ... }
catch (Exception e) { ... } // 兜底

異常傳播與 throws

方法聲明拋出異常


// 強制調用者處理
public void readFile(String path) throws IOException {
    Files.readAllLines(Paths.get(path)); // 拋出 IOException
}

// 鏈式傳播
public void process() throws IOException {
    readFile("data.txt"); // 不捕獲,繼續拋出
}

// 最終由 JVM 處理(打印堆疊並終止)
public static void main(String[] args) throws Exception {
    process();
}

自定義異常設計


// 業務異常:繼承 RuntimeException(非受檢)或 Exception(受檢)
public class InsufficientBalanceException extends RuntimeException {
    private final BigDecimal balance;
    private final BigDecimal required;
    
    public InsufficientBalanceException(BigDecimal balance, BigDecimal required) {
        super(String.format("餘額不足:當前 %s,需 %s", balance, required));
        this.balance = balance;
        this.required = required;
    }
    
    // 提供業務數據供上層決策
    public BigDecimal getBalance() { return balance; }
    public BigDecimal getRequired() { return required; }
}

Java 7+ 進階特性

多重捕獲


try { ... }
catch (IOException | SQLException e) { // 同一塊處理多種異常
    log.error("IO/DB 錯誤", e);
}

try-with-resources 自動關閉


// 實現 AutoCloseable 的資源自動關閉,即使異常也安全
try (FileInputStream fis = new FileInputStream("file.txt");
     BufferedReader br = new BufferedReader(new InputStreamReader(fis))) {
    return br.readLine();
} // 編譯器自動生成 finally 關閉代碼

異常抑制


try (Resource r = new Resource()) {
    throw new Exception("主異常");
} catch (Exception e) {
    // e.getSuppressed() 獲取資源關閉時拋出的被抑制異常
    for (Throwable t : e.getSuppressed()) {
        log.warn("被抑制異常", t);
    }
}

最佳實踐總結

原則說明
具體捕獲捕獲具體異常類,避免 catch (Exception)
異常轉換底層異常包裝為業務異常,保留原因鏈 new BizEx(cause)
不吞沒異常空 catch 塊是大忌,至少記錄日誌
資源安全IO/連接/鎖 必用 try-with-resources
文檔異常Javadoc @throws 標註方法可能拋出的異常
失敗快速參數驗證失敗立即拋出 IllegalArgumentException
區分類型編程錯誤用 RuntimeException,環境/業務錯誤用受檢異常

常見反模式

  • 控制流異常:用異常替代 if/return 控制循環
  • 巨大 try 塊:try 塊包含大量無關代碼,難以定位問題
  • 日誌後再拋:同一異常被多次記錄,日誌噪音大
  • 棄棄受檢異常:catch 後只打印不處理,調用者不知情
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved