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

Java 異常與錯誤處理完整指南:體系、最佳實踐與進階技巧

     編輯:關於JSP

異常與錯誤的本質區別

特性Exception (異常)Error (錯誤)
可處理性開發者可捕獲、恢復、記錄系統級故障,通常無法恢復
典型例子NullPointerException, IOExceptionOutOfMemoryError, StackOverflowError
處理責任業務代碼責任JVM/運行時環境責任
繼承鏈Throwable → ExceptionThrowable → Error

異常體系分類

Throwable
├── Error                 // 嚴重系統錯誤,不建議捕獲
└── Exception             // 可處理異常
    ├── RuntimeException  // 運行時異常(非受檢)
    │   ├── NullPointerException
    │   ├── ArrayIndexOutOfBoundsException
    │   ├── ArithmeticException
    │   └── ClassCastException
    └── Checked Exception // 編譯時異常(受檢)
        ├── IOException
        ├── SQLException
        ├── ClassNotFoundException
        └── InterruptedException

判斷標準:繼承 RuntimeException 或 Error 為非受檢異常,其餘為受檢異常。編譯器強制要求受檢異常必須 try-catch 或 throws 聲明。

異常處理核心語法

基本結構

try {
    // 風險代碼
} catch (SpecificException e) {
    // 處理特定異常
} catch (AnotherException e) {
    // 多重捕獲
} finally {
    // 清理代碼,無論是否異常都執行
}

合法組合規則

  • try-catch ✓
  • try-finally ✓
  • try-catch-finally ✓
  • catch-finally ✗(缺少 try)

Java 7+ 多異常捕獲與資源管理


// 多異常合併捕獲
try {
    riskyOperation();
} catch (IOException | SQLException e) {
    log.error("IO 或 SQL 異常", e);
    throw new BusinessException(e);
}

// Try-with-resources 自動關閉實現 AutoCloseable 的資源
try (FileInputStream fis = new FileInputStream("data.txt");
     BufferedReader reader = new BufferedReader(new InputStreamReader(fis))) {
    return reader.readLine();
}

進階模式與最佳實踐

1. 異常鏈:保留原始堆棧

try {
    parseConfig();
} catch (ParseException e) {
    // 方式一:構造器傳入 cause (推薦)
    throw new ConfigException("配置解析失敗", e);

    // 方式二:initCause (僅能調用一次)
    // ConfigException ce = new ConfigException("配置解析失敗");
    // ce.initCause(e);
    // throw ce;
}

效果:printStackTrace() 會顯示 Caused by: 鏈,完整保留根因信息。

2. 異常轉換與包裝

// 底層異常 → 業務異常,隱藏實現細節
public User findUser(Long id) {
    try {
        return jdbcTemplate.queryForObject(sql, mapper, id);
    } catch (EmptyResultDataAccessException e) {
        throw new UserNotFoundException("用戶不存在: " + id, e);
    } catch (DataAccessException e) {
        throw new DataAccessFailureException("數據庫訪問失敗", e);
    }
}

3. 自定義異常設計原則

// 業務異常基類
public class BusinessException extends RuntimeException {
    private final String errorCode;
    public BusinessException(String errorCode, String message) {
        super(message);
        this.errorCode = errorCode;
    }
    public BusinessException(String errorCode, String message, Throwable cause) {
        super(message, cause);
        this.errorCode = errorCode;
    }
}

// 具體業務異常
public class InsufficientBalanceException extends BusinessException {
    public InsufficientBalanceException(String accountId, BigDecimal required) {
        super("INSUFFICIENT_BALANCE",
              String.format("賬戶 %s 餘額不足,需 %s", accountId, required));
    }
}

4. finally 中的陷阱

public int trickyFinally() {
    try {
        return 1;
    } finally {
        return 2; // 覆蓋 try 的返回值!編譯器警告但合法
    }
}
// 結果:返回 2

原則:finally 僅用於清理(關閉流、釋放鎖),嚴禁包含 return/throw/break/continue。

實戰案例分析

案例一:文件讀取的正確資源管理

public String readFirstLine(String path) throws IOException {
    // Java 7+ 推薦
    try (BufferedReader br = Files.newBufferedReader(Paths.get(path))) {
        return br.readLine();
    }
    // 自動調用 br.close(),即使 readLine() 拋異常
}

案例二:避免異常吞沒

// 錯誤示範:吞沒異常
try {
    saveData();
} catch (Exception e) {
    log.error("保存失敗"); // 缺少 e,堆棧丟失!
}

// 正確:記錄完整堆棧或重新拋出
try {
    saveData();
} catch (Exception e) {
    log.error("保存失敗", e); // 參數順序:message, throwable
    throw new RuntimeException("保存失敗", e);
}

案例三:繼承中的異常規約

class Parent {
    void process() throws IOException {} // 拋出受檢異常
}

class Child extends Parent {
    @Override
    void process() throws FileNotFoundException {} // 合法:子類異常範圍 ≤ 父類
    // void process() throws Exception {} // 編譯錯誤:範圍過大
    // void process() {} // 合法:不拋出異常
}

性能與調試建議

  1. 避免用異常控制流程:異常構建堆棧開銷大,用於真正異常情況。
  2. 提供有意義的錯誤信息:包含關鍵上下文(ID、參數值、操作步驟)。
  3. 統一異常處理切面:Spring @ControllerAdvice 集中處理,返回標準錯誤碼。
  4. 保護敏感信息:異常日誌勿輸出密碼、Token、PII 數據。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved