我有两个问题:
- 重写方法不能抛出新的检查异常的约束的目的是什么?
- 为什么允许被覆盖的方法只能抛出所有或不抛出,或者在超类中被覆盖方法的 throws 子句中指定的已检查异常的子集?
在这两种情况下,都是因为您要覆盖的基本方法已经使用调用代码设置了合约;如果您可以添加该方法可能抛出的已检查异常,那么您将违反合同。
考虑一个具有引发检查异常Base
的方法的类。您还有一个which 派生自和 overrides 。中的代码正在使用一个变量,但使用 的新实例对其进行初始化,并调用. 合同就是扔而已;扔任何东西都会破坏合同。foo
SomeException
Derived
Base
foo
App
Base b
Derived
b.foo()
foo
SomeException
假设可以在重写的方法中添加新的抛出异常。
class AA{
void method() throws FileNotFoundException{}
}
class BB extends AA{
@Override
void method() throws FileNotFoundException, UnsupportedEncodingException {}
}
现在您创建对对象 BB 的引用 AA 并调用方法
AA a=new BB();
try {
a.method();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
编译器只会让你捕获FileNotFoundException
异常,并且不允许捕获UnsupportedEncodingException
,因为它是从引用 AA 调用的。
但是您可以向覆盖的方法添加几种类型的异常
IOException
-> IOException, FileNotFoundException
) 的子类型,因为它们将被检查,RuntimeException
s覆盖类可以添加行为而不是删除。声明抛出异常的方法 - 是一种行为。
想想如果你有课程A
和B extends A
.
A
实现foo() throws MyException
和B
实现foo() throws OtherException
什么会
A a = new B();
a.foo();
一定要抓吗?
然而,如果B.foo()
只抛出异常的一个子集——它仍然是完全安全的,调用环境将捕获(或声明为抛出)所有A
抛出的异常——并且这样做——它还将处理所有 B。