4

我有两个问题:

  1. 重写方法不能抛出新的检查异常的约束的目的是什么?
  2. 为什么允许被覆盖的方法只能抛出所有或不抛出,或者在超类中被覆盖方法的 throws 子句中指定的已检查异常的子集?
4

4 回答 4

9

在这两种情况下,都是因为您要覆盖的基本方法已经使用调用代码设置了合约;如果您可以添加该方法可能抛出的已检查异常,那么您将违反合同。

考虑一个具有引发检查异常Base的方法的类。您还有一个which 派生自和 overrides 。中的代码正在使用一个变量,但使用 的新实例对其进行初始化,并调用. 合同就是扔而已;扔任何东西都会破坏合同。fooSomeExceptionDerivedBasefooAppBase bDerivedb.foo()fooSomeException

于 2012-06-06T11:14:10.357 回答
3

因为代换原则

简而言之:因为你不应该用新的行为让类层次结构的用户感到惊讶。

这个原则对所有 OO 设计/语言都是通用的,而不是 Java 特有的。

于 2012-06-06T11:16:45.363 回答
2

假设可以在重写的方法中添加新的抛出异常。

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) 的子类型,因为它们将被检查,
  • 如果不必检查新异常 -> all RuntimeExceptions
于 2012-06-06T11:25:38.157 回答
2

覆盖类可以添加行为而不是删除。声明抛出异常的方法 - 是一种行为。

想想如果你有课程AB extends A.
A实现foo() throws MyExceptionB实现foo() throws OtherException

什么会

A a = new B();
a.foo();

一定要抓吗?

然而,如果B.foo()只抛出异常的一个子集——它仍然是完全安全的,调用环境将捕获(或声明为抛出)所有A抛出的异常——并且这样做——它还将处理所有 B。

于 2012-06-06T11:15:10.930 回答