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

Java 異常處理進階:父子類異常聲明規則、finally 陷阱與異常丟失場景

     編輯:Java 相關知識

父子類異常聲明鐵律

子類方法 throws ⊆ 父類方法 throws(子集關係)
子類構造器 throws ⊇ 父類構造器 throws(超集關係)

規則一:方法覆寫 - 異常收斂


class BaseEx extends Exception {}
class SubEx extends BaseEx {}
class OtherEx extends Exception {}

class Parent {
    void work() throws BaseEx {}
}

class Child extends Parent {
    // ✅ 不拋異常
    @Override void work() {}
    
    // ✅ 拋子類異常
    @Override void work() throws SubEx {}
    
    // ❌ 拋父類未聲明異常
    // @Override void work() throws OtherEx {} // Compile Error
    
    // ❌ 拋更寬泛異常
    // @Override void work() throws Exception {} // Compile Error
}

本質:里氏替換原則。父類引用調用時,調用者只預期父類聲明的異常。

規則二:構造器 - 異常透傳


class ParentEx extends Exception {}
class ChildEx extends ParentEx {}

class Parent {
    Parent() throws ParentEx {}
}

class Child extends Parent {
    // ✅ 必須聲明父類異常或其父類
    Child() throws ParentEx { super(); }
    Child(int x) throws Exception { super(); }
    
    // ❌ 未聲明父類異常
    // Child() { super(); } // Compile Error
}

原因:super() 必須首行,無法 try-catch,父類構造器異常必須向上拋出。

規則三:多接口衝突


interface A { void m() throws IOException; }
interface B { void m() throws SQLException; }

class C implements A, B {
    // 唯一解:不拋檢查異常(RuntimeException 除外)
    @Override public void m() {}
}

finally 陷阱:異常丟失

場景一:finally 拋出異常覆蓋原異常


try {
    try { throw new RedException(); }
    finally { throw new BlueException(); } // 丟失 RedException
} catch (Exception e) {
    System.out.println(e); // 僅輸出 BlueException
}

場景二:finally 中 return 吞沒異常


try { throw new RuntimeException("原始"); }
finally { return; } // 異常被吞沒,程式正常結束,無任何輸出

鐵律:finally 中 絕不 拋出異常或 return,否則會掩蓋 try/catch 的原始異常。

最佳實踐

  1. try-with-resources (JDK 7+) 自動關閉資源,抑制異常鏈保留原始異常
  2. 異常鏈保留:throw new BizException("業務失敗", cause)
  3. 不吞沒:catch (Exception e) { log.error("", e); throw e; }
  4. 檢查異常轉非檢查:底層 IOException → 業務層 RuntimeException
  5. 自訂異常體系:BizException extends RuntimeException 統一錯誤碼、訊息

總結

Java 異常處理核心在於契約傳遞(父子類聲明規則)與異常鏈完整性(finally 不丟失)。理解 LSP 對異常聲明的約束、super() 特殊位置導致的構造器規則、finally 掩蓋機制,能避開 90% 異常處理坑。

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