面试题答案
一键面试- finally块执行对异常链传递和处理的影响:
- 当try块抛出一个带异常链的异常时,finally块总会在异常传递给上层调用者之前执行(除非JVM在try块抛出异常后立即终止)。
- finally块中的代码执行不会影响异常链本身的存在。也就是说,异常链的
cause
信息依然保留在抛出的异常对象中。 - 然而,如果finally块中也抛出了异常,那么原来try块抛出的带异常链的异常将会被丢弃,新的异常(finally块抛出的)会被传递给上层调用者,导致原来的异常链丢失。
- 确保异常链信息不丢失的方法:
- 在finally块中避免抛出新的异常。如果在finally块中有可能出现异常情况,应该对其进行捕获并处理,而不是让它抛出从而覆盖try块中抛出的异常。例如:
try {
// 可能抛出带异常链异常的代码
throw new RuntimeException("Outer exception", new IllegalArgumentException("Inner exception"));
} catch (Exception e) {
// 可以在这里处理异常
} finally {
try {
// finally块中可能出现异常的代码
// 比如关闭资源等操作
} catch (Exception f) {
// 捕获并处理finally块中的异常,避免其覆盖try块抛出的异常
System.err.println("Exception in finally block: " + f.getMessage());
}
}
- 如果需要在finally块中重新抛出异常,应该把try块中抛出的异常作为新异常的
cause
重新抛出,以保留异常链信息。例如:
Exception outerException = null;
try {
// 可能抛出带异常链异常的代码
throw new RuntimeException("Outer exception", new IllegalArgumentException("Inner exception"));
} catch (Exception e) {
outerException = e;
throw e;
} finally {
try {
// finally块中可能出现异常的代码
// 比如关闭资源等操作
throw new IOException("Finally block exception");
} catch (Exception f) {
if (outerException != null) {
f.initCause(outerException);
}
throw f;
}
}
这样,即使finally块抛出异常,原来try块抛出的异常信息也作为cause
保留在异常链中。