考虑以下课程:
class X
{
public void met()
{
}
}
和
class Y extends X
{
public void met() throws NullPointerException
{
throw new NullPointerException();
}
}
根据我在其他问题上的阅读(Why can't overriding methods throw exceptions broader than the overridden method?和Java method throwing exception)
我理解子类中的重写方法必须抛出重写方法中抛出的异常的相同或子类。
Java方法是否总是抛出异常类型的异常?
...换句话说,编译器会添加 throws Exception
所以X类看起来像这样
class X {
public void met() throws Exception {
}
}
我想澄清我并没有错误关于始终添加默认异常处理程序Exception的事实。
相关问题:
答案 0 :(得分:8)
有两种类型的例外:已检查的例外(例如解析文本时为ParseException
)和未经检查的例外(例如NullPointerException
)。
已检查的异常必须在方法签名中声明。未选中的例外可能在方法签名中声明。
当覆盖方法(来自界面或超类)时,您只需指定例外,即在实施中 。您不能声明在重写方法中不允许的实现中抛出已检查的异常。
这是允许的:
class X { void someMethod() }
class Y extends X { @Override void someMethod() throws UncheckedException }
这是不允许的:
class X { void someMethod() }
class Y extends X { @Override void someMethod() throws CheckedException }
这也是允许的:
class X { void someMethod() throws CheckException }
class Y extends X { @Override void someMethod() }
答案 1 :(得分:3)
slartidan中their answer所说的完全正确。再解释一下:
如果在方法体内抛出"Checked Exception",则需要处理它(使用catch块)或声明throws-clause
重申之前链接的JLS:
Throwable
Throwable
OutOfMemoryError
)Exception
不捕获错误RuntimeException
。这是一个扩展Exception
错误和运行时异常在编译时 未经过检查,因为这正是“已检查异常”的含义。
您可以在代码中的任何位置投放Error
和RuntimeException
。
现在它如何影响throws子句:
throws子句指定对声明的方法的调用可能导致指定的异常。有趣的是,抛出期望Throwable
,这使得以下声明有效:
public void method() throws StackOverflowError, NullPointerException {
//...
}
在throws子句中声明未检查的异常时没有编译器效果,但有时为了清楚起见在源代码中这样做。
此外,有时在JavaDoc中提到了这种异常(例如BigInteger#divide
)
但是,当重写方法时,编译器会检查throws子句。在覆盖方法时,它与可见性规则有些相似。这意味着可以始终执行抛出未经检查的异常(并声明相应的throws子句)。声明后有效:
public interface Demo {
void test();
}
public class DemoImpl implements Demo {
public void test() throws NullPointerException {
throw new NullPointerException();
}
}
反之亦然。 throws子句中未经检查的异常会被编译器忽略,因为它们与编译时检查无关:
public interface Demo {
void test() throws NullPointerException;
}
public class DemoImpl implements Demo {
public void test() {
throw new NullPointerException();
}
}
throws-clause继承的一般规则是:一个接口来统治它们:接口必须声明所有可以通过实现类抛出的已检查异常。换句话说:
实现类可以在实现方法的throws-clause中的接口方法的throws-clause中声明已声明的已检查异常的子集
这意味着以下内容有效:
public interface Demo {
void test() throws IOException, ParseException;
}
public class DemoImpl implements Demo {
public void test() throws IOException {
throw new IOException();
}
}
什么是无效的是在实现方法的throws-clause中声明一个未在相应的接口方法子句中声明的已检查异常:
public interface Fail {
void test() throws ParseException;
}
public class FailImpl implements Fail {
public void test() throws IOException {
throw new IOException();
}
}