最近,我看到很多(商业)代码抛出并捕获完全相同的异常,类似于下面的代码:
public class Foo {
public void bar() throws AnException {
// do something (1)
try {
// do something (2) -- able to throw AnException
} catch (AnException ex) {
throw ex;
}
// do something (3)
}
}
将此对比:
public class Foo {
public void bar() throws AnException {
// do something (1)
// do something (2) -- able to throw AnException
// do something (3)
}
}
前者实际上是在行为还是语义上实现了什么呢?它会对代码性能(时间和空间)产生影响还是有助于提高可读性?
P.S。这个问题与this question非常不同。
编辑:除了重新抛出捕获的异常之外,前者的catch
阻止除此之外不会做任何其他事情。
答案 0 :(得分:6)
这违反了基本规则:
代码应该只捕获它知道如何处理的异常。
Oracle的指南建议,每次抛出异常时,都应该为捕获异常的代码提供一些有用的东西(参见Effective Java Exceptions的第3页)。仅仅为了重新抛出异常而捕获异常没有任何实际意义,因为在调用链中没有为其上面的代码添加额外信息,也没有方法本身提取的信息。
答案 1 :(得分:5)
确定假设您提供的代码毫无意义。 当您想以某种方式处理此异常(例如,记录它)但希望在堆栈跟踪中进一步处理时,重新抛出异常是有意义的。
关于商业代码,也许你看到它的原因是最初有一些处理逻辑被删除但是异常重新抛出没有被删除。我多次看到这种情况。
答案 2 :(得分:1)
您发布的代码中没有try/catch
的原因。与@nickolay.laptev's answer一样,我相信如果您在商业代码中发现这一点,那么它可能会遗留下来之前那些曾经有意义的内容。
除了某种部分错误处理之外,还有另一个用例来简单地捕获和重新抛出异常。这可以防止异常被后续的更通用的catch
子句捕获。因此,例如,如果您想处理AnException
的除实例以外的每个异常,您可能需要进行类型检查:
try {
// stuff
} catch (Exception ex) {
if (ex instanceof AnException) {
throw ex; // rethrow since we're not handling it
} else {
// handle all other exceptions
}
}
或使用类似的东西(在我看来,它更干净,更易读):
try {
// stuff
} catch (AnException) {
throw ex;
} catch (Exception ex) {
// handle all other exceptions
}
然后,如果您以后决定不处理所有其他异常,则删除第二个catch
子句并最终得到您发布的代码。