我试图从一个Runnable对象内抛出异常,像这样:
class ExceptionRunnable implements Runnable {
@Override
public void run() throws Exception {
throw new Exception("ExceptionRunnable");
}
}
编译错误:xxx.ExceptionRunnable.run()没有实现java.lang.Runnable.run()重写的run()不会抛出java.lang.InterruptedException。
这真的很奇怪,我在run
函数中抛出了一个new Exception
,但是编译器说我没有抛出任何东西。我在windows上使用jdk1.8。
如何处理?
编译代码时:
class ExceptionRunnable implements Runnable {
@Override
public void run() throws Exception {
throw new Exception("ExceptionRunnable");
}
}
编译器显示以下错误:
java: run() in ExceptionRunnable cannot implement run() in java.lang.Runnable
overridden method does not throw java.lang.Exception
为什么?因为您要重写的方法-Runnable.run()
-具有此签名(注意缺少throws
子句):
void run()
要解决第一个问题,请将代码更改为:
public void run() throws Exception {
到this,以便签名匹配:
public void run() {
修改之后,您将发现下一个编译错误:
java: unreported exception java.lang.Exception; must be caught or declared to be thrown
这是说你自己的代码抛出了一个Exception
,它既没有被捕获,也没有在抛出子句中声明。您已经发现,您不能将它添加到抛出子句中—这是您最初尝试做的事情。因此,另一种选择是在run()
方法中捕获异常,如下所示:
@Override
public void run() {
try {
throw new Exception("ExceptionRunnable");
} catch (Exception e) {
e.printStackTrace();
}
}
另一种选择是抛出RuntimeException
,如下所示,但是您应该只有意地这样做,充分理解在代码中引入未检查异常意味着什么。
@Override
public void run() {
throw new RuntimeException("ExceptionRunnable");
}
看起来像以前问过的一个类似的问题:Java:如何重写方法并抛出异常?
抛出一个RuntimeException会满足你的要求吗?
class ExceptionRunnable implements Runnable {
@Override
public void run() {
throw new RuntimeException("ExceptionRunnable");
}
}
根据方法重写的规则不能声明抛出检查异常(或Throwable
以内的父类类型),在子类中重写方法时未被父类声明。
引用语言规范:
如果m2有抛出子句提到任何检查异常类型,那么m1必须有一个抛出子句,否则会出现编译时错误.
当子节点的行为不太安全时,它的父节点也违反了Liskov替换原则,该原则规定,期望父节点实例的客户端代码应该能够在不知道它的情况下使用它的子节点。因为万一孩子有不安全的行为,客户端不会用适合父母的代码来处理它。
超类型Exception
是检查(即编译器应该确保无论何时可能发生它都被正确处理),方法run()
不声明抛出任何检查异常,因此你不能通过在throws
关闭中包含Exception
来覆盖run()
。
可以在run()
的throws
关闭语句中包含任何类型的未检查异常。下面的代码是有效的,可以编译为:
class MyRunnable implements Runnable {
@Override
public void run() throws RuntimeException {
// todo
}
}
代码可能抛出的所有检查异常应该在run()
内部处理,不能传播给调用者:
class MyRunnable implements Runnable {
@Override
public void run() throws RuntimeException {
try {
Thread.sleep(1_000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
注意:避免向throw
声明,也避免捕获Exception
或Throwable
这样的超类型,这是一个坏习惯。越具体越好