您的两个代码示例之间的行为没有区别。(特别是,堆栈跟踪是在创建异常时记录的,而不是在抛出异常时记录的,因此重新抛出的异常仍将具有原始堆栈跟踪)。通常,人们因此使用更简单的成语。
这并不是说重新抛出没有它的用途。例如,如果您想处理除 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;
}
}
}
值得注意的是,当人们说 rethrow 时,有些人的意思是抛出不同的异常,如下例所示:
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);
}
}
这种模式的优点是用可能相关的附加信息来装饰原始异常(在上面的示例中:无法处理哪些数据)。请注意,原始异常被传递给新异常的构造函数,因此它的堆栈跟踪不会丢失。