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

Java 異常體系架構:Error、Exception、RuntimeException 核心差異與處理策略

     編輯:Java 相關知識

異常繼承體系圖

java.lang.Throwable
├── java.lang.Error                 // 嚴重錯誤,不可恢復 (OOM, StackOverflow)
└── java.lang.Exception             // 受檢異常基類
    ├── java.lang.RuntimeException  // 非受檢異常基類 (NPE, IndexOutOfBounds)
    │   ├── NullPointerException
    │   ├── IllegalArgumentException
    │   └── ...
    ├── java.io.IOException         // 典型受檢異常
    ├── java.sql.SQLException
    ├── java.text.ParseException
    └── ... (其他受檢異常)

三大類別核心差異

維度ErrorException (受檢)RuntimeException (非受檢)
繼承自ThrowableExceptionException
編譯器強制處理否是 (try-catch 或 throws)否
典型場景JVM 級故障、資源耗盡外部資源失敗 (IO、DB、網絡)編程邏輯錯誤、參數非法
是否應捕獲處理絕不必須可選 (通常由全局處理器捕獲)
代表類OutOfMemoryError、StackOverflowError、NoClassDefFoundErrorIOException、SQLException、ParseException、ClassNotFoundExceptionNullPointerException、ArrayIndexOutOfBoundsException、IllegalStateException

處理策略決策樹

發生異常
  │
  ├─ 是 Error? ──是──► 不捕獲,讓 JVM 崩潰/重啟,排查根因 (內存洩漏、死循環、類加載失敗)
  │
  └─ 否 (是 Exception)
      │
      ├─ 是 RuntimeException? ──是──► 
      │       ├─ 能預防? ──是──► 修正代碼邏輯 (空指針檢查、邊界判斷)
      │       └─ 不能預防? ──► 全局異常處理器記錄日誌、返回友好錯誤頁/JSON
      │
      └─ 否 (受檢異常)
          │
          ├─ 當前層能有意義處理? ──是──► try-catch 處理 (重試、降級、轉換錯誤碼)
          │
          └─ 否 ──► 
                  ├─ 包裝為 RuntimeException 拋出 (保留原異常作為 cause)
                  └─ 或在方法簽名 throws 聲明 (API 契約要求)

代碼示範:標準處理模式

1. 受檢異常 → 業務異常轉換 (推薦)

@Repository
public class UserDao {
    public User findById(Long id) {
        try {
            return jdbcTemplate.queryForObject("SELECT * FROM user WHERE id=?", 
                (rs, rowNum) -> new User(rs.getLong("id"), rs.getString("name")), id);
        } catch (EmptyResultDataAccessException e) {
            throw new BusinessException("USER_NOT_FOUND", "用戶不存在: " + id, e);
        } catch (DataAccessException e) {
            throw new SystemException("DB_ERROR", "數據庫訪問失敗", e);
        }
    }
}

2. 運行時異常 → 全局統一處理 (Spring Boot)

3. 防禦性編程:參數校驗拋出運行時異常

public void transfer(Account from, Account to, BigDecimal amount) {
    // 非空檢查
    Objects.requireNonNull(from, "轉出賬戶不能為空");
    Objects.requireNonNull(to, "轉入賬戶不能為空");
    Objects.requireNonNull(amount, "金額不能為空");
    
    // 業務規則校驗
    if (amount.compareTo(BigDecimal.ZERO) <= 0) {
        throw new IllegalArgumentException("轉賬金額必須大於零");
    }
    if (from.getBalance().compareTo(amount) < 0) {
        throw new InsufficientBalanceException("餘額不足: " + from.getBalance());
    }
    
    // 核心邏輯...
}

常見反模式與修正

反模式問題修正
catch (Exception e) { e.printStackTrace(); }吞噬異常,調用方不知失敗至少重新拋出或包裝拋出
throws Exception 在方法簽名調用方無法針對性處理聲明具體異常或包裝為運行時異常
捕獲 Error 類掩蓋嚴重故障絕不捕獲 Error
用異常控制業務流程性能差、可讀性差用條件判斷、Optional、Result 模式

總結

  • Error:JVM 級災難,不捕獲,靠監控告警
  • 受檢異常:外部依賴不可控風險,要么當前層處理,要么包裝為運行時異常拋出
  • 運行時異常:編程錯誤,優先預防,不可預防則全局統一處理
  • 異常鏈 cause 必須保留,便於根因排查
  • 業務代碼盡量無 try-catch,交由切面/全局處理器
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved