如果不需要调整异常类型,则可以重新抛出(进一步抛出)同一实例,而不进行任何更改:
catch (IOException e) {
throw e;
}
如果确实需要调整异常类型,则可以将 e
(作为原因)包装到所需类型的新异常中。
catch (IOException e) {
throw new IllegalArgumentException(e);
}
我认为所有其他方案都是代码异味。您的第二个代码段就是一个很好的例子。
以下是可能弹出的问题的答案。
为什么我要重新抛出异常?
你可以放手。但是,如果发生这种情况,您将无法在此级别上做任何事情。
当我们在方法中捕获异常时,我们仍然处于该方法中,并且可以访问其范围(例如局部变量及其状态)。在我们重新抛出异常之前,我们可以做任何我们需要做的事情(例如.log一条消息,把它发送到某个地方,制作当前状态的快照)。
为什么我要调整异常?
根据经验,
较高层应捕获较低级别的异常,并在其位置上抛出可以用较高级别抽象来解释的异常。
有效的 Java - 第 2 版 - 项 61:引发适合于抽象的异常
换句话说,在某些时候,一个晦涩难懂的东西应该变成一个显眼的 。IOException
MySpecificBusinessRuleException
我称之为“调整异常类型”,聪明人称之为异常翻译(特别是异常链接)。
为了清楚起见,让我们举一些愚蠢的例子。
class StupidExample1 {
public static void main(String[] args) throws IOException {
try {
throw new IOException();
} catch (IOException e) {
throw new IOException(new IOException(e));
}
}
}
导致详细的堆栈跟踪,如
Exception in thread "main" java.io.IOException: java.io.IOException: java.io.IOException
at StupidExample1.main(XXX.java:XX)
Caused by: java.io.IOException: java.io.IOException
... 1 more
Caused by: java.io.IOException
at StupidExample1.main(XXX.java:XX)
可以(并且应该)有效地减少到
Exception in thread "main" java.io.IOException
at StupidExample1.main(XXX.java:XX)
另一个:
class StupidExample2 {
public static void main(String[] args) {
takeString(new String(new String("myString")));
}
static void takeString(String s) { }
}
很明显,这是一个冗长的版本,应该重构为后者。new String(new String("myString"))
"myString"