1

我试图理解为什么子类不能覆盖父类中的方法实现以捕获异常但在捕获错误时没有问题的区别,

例如在下面的场景中,当我从 throws 子句中删除“异常”时,它编译得很好。

class Supertest {

    public void amethod(int i, String s) {

    }

}

public class test extends Supertest {

    public void amethod(int i, String s) throws Error, Exception {

    }

}
4

4 回答 4

8

Error是未经检查的异常。Exception是一个检查异常。就这么简单。所以有这样的代码应该是合理的:

Supertest x = new test();
x.amethod(10, "foo");

...但test.amethod()试图对调用者强加一个检查异常,以便调用者要么必须捕获它,要么传播它。由于它覆盖的方法没有声明该异常,因此覆盖方法也不能。

如评论中所述,从根本上讲,您不能用“更具限制性”的方法覆盖一种方法 - 对原始方法的任何调用都必须对覆盖有效。

从JLS 的第 8.4.8.3 节

更准确地说,假设 B 是一个类或接口,A 是 B 的超类或超接口,B 中的方法声明 n 覆盖或隐藏 A 中的方法声明 m。那么:

  • 如果 n 具有提及任何已检查异常类型的 throws 子句,则 m 必须具有 throws 子句,否则会发生编译时错误。
  • 对于 n 的 throws 子句中列出的每个检查异常类型,相同的异常类或其超类型之一必须出现在 m 的 throws 子句的擦除(第 4.6 节)中;否则,会发生编译时错误。
于 2013-09-18T17:27:45.267 回答
2

Throw 子句必须是协变的。

这类似于覆盖方法的返回类型的要求:

SuperClass
    Pet method()

SubClass
    Cat method()

Cat是 的子类型Pet,因此覆盖是合法的。

同样的原则也适用于throws子句,它也是方法输出的一部分。

SuperClass
    Pet method() throws PetException

SubClass
    Cat method() throws CatException

如果CatException是 的子类型,则这是合法的PetException

如果方法的 throw 子句为空,则它是隐式的RuntimeException|Error。所有覆盖方法只能抛出它的子类型。Excepiton|RuntimeException|Error不是 的子类型RuntimeException|Error

于 2013-09-18T17:34:44.127 回答
0

说你有

SuperTest superTest = new test();
superTest.amethod();

在编译时,方法是用变量的声明或静态类型解析的。SuperTest#amethod声明时不抛出检查异常,因此其Exception子项需要遵循这些规则。

Error是未经检查的异常。它不需要被抓住。因此,父方法声明不会限制它。

于 2013-09-18T17:28:10.607 回答
0

如果超类方法未声明任何异常,则子类重写方法不能声明任何已检查异常。

这里是Exception选中的和Error未选中的。所以你不能 throw Exception
参考http://www.javatpoint.com/exception-handling-with-method-overriding

于 2013-09-18T17:30:09.110 回答