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

Java 異常拋出後代碼執行流程完整分析

     編輯:Java 相關知識

核心結論

未被捕獲的異常拋出後,後續代碼永不執行(編譯期報錯「unreachable statement」);被 try-catch 捕獲且 catch 塊不拋出新異常,後續代碼正常執行。

三種場景實測

場景一:直接拋出,無捕獲 → 編譯錯誤

public void test1() throws Exception {
    throw new Exception("參數錯誤");
    System.out.println("異常後"); // 編譯錯誤:unreachable statement
}

原因:編譯器確定該行不可達,直接阻止編譯。

場景二:try-catch 捕獲,不再拋出 → 正常執行

public void test2() {
    try {
        throw new Exception("參數錯誤");
    } catch (Exception e) {
        e.printStackTrace(); // 僅記錄,不拋出
    }
    System.out.println("異常後"); // 正常輸出
}

場景三:if 塊中拋出 → 運行時不執行後續代碼,但編譯通過

public void test3() throws Exception {
    if (true) {
        throw new Exception("參數錯誤");
    }
    System.out.println("異常後"); // 編譯通過,但運行時永不執行
}

區別:編譯器無法確定 if 條件恒真,故允許編譯;JVM 運行時異常拋出導致方法終止。

編譯期 vs 運行期異常處理規則

異常類型代表處理要求不處理後果
受檢異常 (Checked)IOException、SQLException、ParseException強制 try-catch 或 throws 聲明編譯錯誤
非受檢異常 (Unchecked/Runtime)NullPointerException、IndexOutOfBoundsException、IllegalArgumentException可選處理運行時拋出,JVM 默認打印堆棧並終止線程
ErrorOutOfMemoryError、StackOverflowError不應捕獲處理JVM 級別嚴重錯誤,通常不可恢復

最佳實踐模式

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

public void add(int index, Element element) {
    if (index < 0 || index > size) {
        throw new IndexOutOfBoundsException("索引越界: " + index); // 無需聲明 throws
    }
    // 後續代碼正常執行...
}

2. 業務異常轉換:捕獲受檢異常包裝為非受檢異常

public User findById(Long id) {
    try {
        return jdbcTemplate.queryForObject(sql, mapper, id);
    } catch (EmptyResultDataAccessException e) {
        throw new BusinessException("用戶不存在: " + id, e); // 運行時異常
    } catch (DataAccessException e) {
        throw new SystemException("數據庫訪問失敗", e); // 運行時異常
    }
}

3. finally 塊確保資源釋放

public void processFile(String path) {
    BufferedReader reader = null;
    try {
        reader = new BufferedReader(new FileReader(path));
        // 處理邏輯
    } catch (IOException e) {
        throw new RuntimeException("文件讀取失敗", e);
    } finally {
        if (reader != null) {
            try { reader.close(); } catch (IOException ignored) {}
        }
    }
    // 此處代碼正常執行(若無異常拋出)
}

異常處理決策樹

發生異常
  │
  ├─ 能在當前層級有意義處理? ──是──► try-catch 處理,記錄日誌,嘗試恢復或返回默認值
  │
  └─ 否
      │
      ├─ 是受檢異常? ──是──► 包裝為非受檢異常拋出 (throws RuntimeException)
      │
      └─ 否 (已是運行時異常) ──► 直接拋出,由全局異常處理器統一處理

總結

  • throw 語句後的代碼不可達,編譯器會報錯(無條件拋出時)
  • try-catch 捕獲後,若 catch 不再拋出,方法繼續執行
  • 運行時異常 適合編程錯誤/不可恢復錯誤,受檢異常 適合可預期可恢復的業務情況
  • 統一使用全局異常處理器 (Spring @ControllerAdvice) 處理未捕獲異常,避免業務代碼充斥 try-catch
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved