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

Java 異常處理完全指南:try-catch-finally、throws、自訂異常與最佳實踐

     編輯:Java 相關知識

異常體系速覽

Throwable
├── Error(嚴重錯誤,如 OutOfMemoryError,不應捕捉)
└── Exception
    ├── RuntimeException(非受檢,如 NPE、IndexOutOfBounds,邏輯錯誤)
    └── 受檢例外(編譯強制處理,如 IOException、SQLException)

Java 強制規定:**除 Error 和 RuntimeException 外,所有例外必須被捕捉或聲明拋出**,這是強健代碼的基石。

兩種處理機制

1. 傳遞給調用者:throws


public void readFile(String path) throws IOException {
    Files.readAllLines(Paths.get(path)); // 未捕捉,拋給調用者
}
  • 適用於無法在當前層級妥善處理、需上層業務邏輯決策的受檢例外。
  • 調用鏈最終到 main() 若仍未處理,JVM 列印堆疊並終止程式。

2. 就地處理:try-catch-finally


try {
    // 可能拋出例外的代碼(保持最小範圍)
    String content = Files.readString(path);
    process(content);
} catch (FileNotFoundException e) {
    log.warn("檔案不存在: {}", path);
    throw new BusinessException("資料來源缺失", e);
} catch (IOException e) {
    log.error("讀取失敗", e);
    throw new BusinessException("系統暫時不可用", e);
} finally {
    // 無論是否發生例外、是否捕捉、是否 return,都會執行
    // 釋放資源:關閉流、釋放鎖、清理 ThreadLocal
}

關鍵規則與陷阱

規則說明錯誤示範正確做法
catch 順序子類在前,父類在後先 catch Exception 再 catch IOException先 catch IOException 再 catch Exception
finally 必執行即使 try/catch 有 return/throw在 finally 中 return 覆蓋原返回值只做清理,不 return/throw
資源關閉JDK 7+ try-with-resources 自動關閉手動 close() 易漏、順序錯try (InputStream in = Files.newInputStream(path)) { ... }
異常轉譯保留原始堆疊throw new RuntimeException(e.getMessage())throw new BizException("業務含義", e)
空 catch吞掉錯誤 = 製造定時炸彈catch (Exception e) {}至少記錄日誌或重拋

自訂異常設計規範


// 業務例外:繼承 RuntimeException,攜帶錯誤碼
public class BizException extends RuntimeException {
    private final int code;
    public BizException(int code, String message) { super(message); this.code = code; }
    public BizException(int code, String message, Throwable cause) { super(message, cause); this.code = code; }
    public int getCode() { return code; }
}

// 使用範例
if (balance < amount) {
    throw new BizException(1001, "餘額不足,當前:" + balance + ",需求:" + amount);
}

全域異常處理器


@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(BizException.class)
    public R handleBiz(BizException e) {
        log.warn("業務異常 [{}] {}", e.getCode(), e.getMessage());
        return R.fail(e.getCode(), e.getMessage());
    }
    @ExceptionHandler(Exception.class)
    public R handleSys(Exception e) {
        log.error("系統異常", e); // 完整堆疊進 ELK
        return R.fail(500, "系統繁忙,請稍後再試");
    }
}

最佳實踐清單

  1. 受檢例外用於可恢復業務場景,非受檢用於程式錯誤/前置條件違反。
  2. 捕捉即處理或包裝重拋,絕不空 catch。
  3. 盡早失敗:參數驗證用 Objects.requireNonNull、Preconditions.checkArgument 主動拋出。
  4. 資源用 try-with-resources,拒絕手動 close()。
  5. 日誌記錄完整堆疊:log.error("msg", e),而非 log.error(e.getMessage())。
  6. 異常不作流程控制:預期情況用 Optional、Result、布林值。

總結

異常處理的核心不是「捕捉錯誤」,而是「建立可信任的錯誤傳遞管道」。正確的策略讓錯誤在正確層級被正確處理,錯誤資訊完整保留,資源確定釋放,業務語義清晰表達。這才是強健 Java 系統的基石。

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