子類方法
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() {}
}
try {
try { throw new RedException(); }
finally { throw new BlueException(); } // 丟失 RedException
} catch (Exception e) {
System.out.println(e); // 僅輸出 BlueException
}
try { throw new RuntimeException("原始"); }
finally { return; } // 異常被吞沒,程式正常結束,無任何輸出
鐵律:finally 中 絕不 拋出異常或 return,否則會掩蓋 try/catch 的原始異常。
throw new BizException("業務失敗", cause)catch (Exception e) { log.error("", e); throw e; }BizException extends RuntimeException 統一錯誤碼、訊息Java 異常處理核心在於契約傳遞(父子類聲明規則)與異常鏈完整性(finally 不丟失)。理解 LSP 對異常聲明的約束、super() 特殊位置導致的構造器規則、finally 掩蓋機制,能避開 90% 異常處理坑。