我试图理解为什么子类不能覆盖父类中的方法实现以捕获异常但捕获错误时没有问题的区别
例如在下面的场景中,当我从throws子句中删除“Exception”时,它编译得很好。
class Supertest {
public void amethod(int i, String s) {
}
}
public class test extends Supertest {
public void amethod(int i, String s) throws Error, Exception {
}
}
答案 0 :(得分:8)
Error
是未经检查的例外。 Exception
是checked exception。就这么简单。因此,使用这样的代码应该是合理的:
Supertest x = new test();
x.amethod(10, "foo");
...但test.amethod()
尝试在调用者上强加一个已检查的异常,以便调用者必须捕获它或传播它。由于它覆盖的方法不会声明该异常,因此重写方法也不能。
正如评论中所述,从根本上说,你不能用一个“限制性更强”的方法覆盖一个方法 - 对原始方法的任何调用仍必须对覆盖有效。
来自JLS的section 8.4.8.3:
更准确地说,假设B是类或接口,A是B的超类或超接口,B中的方法声明n覆盖或隐藏A中的方法声明。然后:
- 如果n有throws子句提到任何已检查的异常类型,则m必须有throws子句,否则会发生编译时错误。
- 对于n的throws子句中列出的每个已检查异常类型,必须在m的throws子句的擦除(第4.6节)中出现相同的异常类或其超类型之一;否则,发生编译时错误。
答案 1 :(得分:2)
投掷条款必须是协变的。
这类似于重写方法的返回类型的要求:
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
的子类型。
答案 2 :(得分:0)
说你有
SuperTest superTest = new test();
superTest.amethod();
在编译时,使用声明或静态类型的变量解析方法。声明SuperTest#amethod
时不会抛出已检查的异常Exception
,因此其子级需要遵循这些规则。
Error
是未经检查的例外。它不需要被抓住。因此,父方法声明不限制它。
答案 3 :(得分:0)
如果超类方法没有声明任何异常,则子类重写方法不能声明任何已检查的异常。
此处Exception
已选中且Error
未选中。因此您无法抛出Exception
。
参考http://www.javatpoint.com/exception-handling-with-method-overriding