任何人都可以确认以下关于定义方法重写时抛出的异常的方法吗?我想确保我清楚地理解它。
给出以下代码:
class A
{
public void doStuff() throws IllegalArgumentException{}
}
class B extends A
{
public void doStuff() throws NumberFormatException{}
}
class C extends A
{
public void doStuff() throws Exception{}
}
只有A类和B类应该编译而不是C类。当覆盖一个方法时,你可以缩小抛出的类,但是不能像C类那样扩展它。我相信这背后的原因是以下代码中的例子: / p>
class D
{
doIt(A a)
{
try
{
a.doStuff();
}
catch(IlligalArgumentException e){}
}
}
A类可以被扩展任意次,因此doStuff()方法也可能被覆盖任意次,但无论如何,上面的try catch总是会捕获异常。
但是如果允许扩展,上面的代码可能会错过抛出的异常,并且应用程序中会出现意外结果。
这是正确的想法吗?还有什么我想念的吗?
由于
答案 0 :(得分:1)
如果方法声明抛出给定的异常,则子类中的重写方法只能声明抛出该异常或其子类。这是因为多态性。 所以imo,你的想法是正确的。
答案 1 :(得分:1)
作为参考,Java Language Specification说
覆盖或隐藏其他方法的方法,包括方法 实现接口中定义的抽象方法,可能不是 声明抛出比被覆盖的或更多的已检查异常 隐藏方法。
和
更准确地说,假设
B
是一个类或接口,A
是一个B
的超类或超接口,以及n
中的方法声明B
覆盖或隐藏m
中的方法声明A
。然后:
如果
n
有一个throws子句,提到任何已检查的异常类型, 然后m
必须有一个throws子句,否则会发生编译时错误。对于
n
的throws子句中列出的每个已检查异常类型, 必须出现相同的异常类或其中一个超类型 删除m
的throws子句(第4.6节); 否则,编译时 发生错误。如果
m
的未删除的throws子句不包含超类型n
的throws子句中的每个异常类型,编译时 发生未经检查的警告。
因此规则适用于已检查的异常类型,而不是未选中。