子類構造器:
throws必須 包含 父類構造器異常(父 ⊆ 子)
子類方法:throws必須 子集 於父類方法異常(子 ⊆ 父)
super())super() 必須置於首行,無法被 try-catch 包裹class BaseEx extends Exception {}
class SubEx extends BaseEx {}
class Parent {
Parent() throws BaseEx {}
Parent(int x) throws SubEx {}
}
class Child extends Parent {
// ✅ 合法:拋出父類異常
Child() throws BaseEx { super(); }
// ✅ 合法:拋出父類異常父類
Child(int x) throws Exception { super(x); }
// ❌ 非法:未聲明父類異常
// Child() { super(); } // Compile Error
// ❌ 非法:拋出無關異常
// Child() throws IOException { super(); } // Compile Error
}
父類引用指向子類對象時,調用者按父類異常契約編程。若子類拋出父類未聲明的異常,調用者無法捕獲 → 破壞多態安全。
interface Service {
void doWork() throws IOException;
}
class BaseService {
void doWork() throws FileNotFoundException {} // 子類異常
}
class Impl extends BaseService implements Service {
// ✅ 合法:不拋異常
@Override void doWork() {}
// ✅ 合法:拋出父類異常子集
@Override void doWork() throws FileNotFoundException {}
// ❌ 非法:拋出父類未聲明異常
// @Override void doWork() throws SQLException {} // Compile Error
// ❌ 非法:實現接口拋出更寬泛異常
// @Override void doWork() throws Exception {} // Compile Error
}
interface A { void m() throws IOException; }
interface B { void m() throws SQLException; }
class C implements A, B {
// 必須同時滿足兩個接口:throws 子集於 IOException ∩ SQLException = 無
// 唯一解:不拋檢查異常
@Override public void m() {}
}
RuntimeException 及其子類 不受聲明約束:
NullPointerExceptionthrows RuntimeException 合法但無意義(文檔用)throws,用 Javadoc @throws 說明throw new ChildException("msg", parentCause) 保留根因Java 異常聲明規則本質是契約繼承:構造器「向上傳遞責任」,方法「向下收斂風險」。理解 LSP 與 super() 調用機制,即可靈活應對所有覆寫場景。