两个代码示例之间的行为没有区别. (特别是,在创建异常时记录堆栈跟踪,而不是在抛出异常时记录,因此重新抛出的异常仍将具有原始堆栈跟踪).通常,人们因此使用更简单的习语.
这并不是说重新抛出没有它的用途.例如,如果您想处理除FooBarExceptions之外的所有异常,您可以编写:
try {
// bad code
} catch (FooBarException e) {
throw e;
} catch (Exception e) {
e.printStackTrace();
}
或者,如果处理异常的决定比简单地检查它的类型更复杂,那么你可以简单地捕获它,如果事实证明你无法处理它,则重新抛出:
for (int attempts = 0; attemps < 6; attempts++) {
try {
return crankyMethod();
} catch (Exception e) {
if (fatal(e)) {
throw e;
} else {
// try again
continue;
}
}
}
值得注意的是,当人们说重新抛出时,有些人意味着抛出不同的异常,如下例所示:
for (int i = 0; i < array.length; i++) {
try {
process(array[i]);
} catch (Exception e) {
throw new RuntimeException("Could not process element at index " + i, e);
}
}
此模式的优点是使用可能相关的其他信息来装饰原始异常(在上面的示例中:无法处理哪些数据).请注意,原始异常将传递给新构造函数的构造函数,因此其堆栈跟踪不会丢失.