为什么被重写的方法不能抛出新的已检查异常

时间:2012-06-06 11:12:23

标签: java

我有两个问题:

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

4 个答案:

答案 0 :(得分:8)

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

考虑使用方法Base的类foo,该方法会抛出已检查的异常SomeException。您还有Derived,其源自Base并覆盖fooApp中的代码使用Base b变量,但使用Derived的新实例进行初始化,并调用b.foo()。合同是foo只抛出SomeException;抛出任何其他东西都违反了合同。

答案 1 :(得分:2)

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

如果您有课程AB extends A,请考虑会发生什么。
A实施foo() throws MyExceptionB实施foo() throws OtherException

会是什么

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

必须赶上?

但是,如果B.foo()仅抛出异常的一部分 - 它仍然非常安全,则调用环境将捕获(或声明为抛出)所有A抛出的异常 - 并且这样做 - 它也将处理所有B的。

答案 2 :(得分:2)

由于the substitution principle

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

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

答案 3 :(得分: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();
}

Compilator将只允许您捕获FileNotFoundException异常,并且不会允许捕获UnsupportedEncodingException,因为它是从参考AA调用的。

但是你可以为重写方法添加几种类型的例外

  • 如果它们是已抛出异常的子类型(IOException - > IOException, FileNotFoundException),因为它们会被检查,
  • 如果不必检查新例外 - >所有RuntimeException s