这意味着,如果一个方法声明抛出一个给定的异常,那么子类中的重写方法只能声明抛出该异常或其子类。例如:
class A {
public void foo() throws IOException {..}
}
class B extends A {
@Override
public void foo() throws SocketException {..} // allowed
@Override
public void foo() throws SQLException {..} // NOT allowed
}
SocketException extends IOException
,但不会。SQLException
这是因为多态性:
A a = new B();
try {
a.foo();
} catch (IOException ex) {
// forced to catch this by the compiler
}
如果决定抛出 ,那么编译器不能强迫你抓住它,因为你引用的是它的超类的实例 - 。另一方面,任何子类都将由处理B
SQLException
B
A
IOException
IOException
您需要能够通过其超类引用对象的规则是Liskov替换原理。
由于未经检查的异常可以在任何地方抛出,因此它们不受此规则的约束。如果需要,可以将未经检查的异常作为文档形式添加到 throws 子句中,但编译器不会强制执行任何有关它的内容。