【问题标题】:Java lost exceptionJava丢失异常
【发布时间】:2014-11-03 07:02:04
【问题描述】:
假设我们有以下方法(一个非常简化的版本):
void doSomething() {
try {
throw new Exception("A");
} finally {
throw new Exception("B");
}
}
在调用者方法中捕获到带有消息“B”的异常。基本上,如果 finally 块也抛出一些异常,有没有办法知道 try 块中抛出了哪个异常?假设方法 doSomething() 不能被修改。
【问题讨论】:
标签:
java
exception
try-catch
finally
【解决方案1】:
Section 14.20.2 of the JLS 状态:
如果 try 块的执行由于抛出值 V 而突然完成,...
...
如果 finally 块由于原因 S 突然完成,则 try 语句由于原因 S 突然完成(并且值 V 的抛出被丢弃并忘记)。
Java 必须丢弃原始异常 V(“突然完成”)和整个 try-finally 块“突然完成”S(finallyException,“B”)。
无法找回原来的try块异常“A”,对应JLS中的V。
【解决方案2】:
finally 块将消耗来自 try-catch 块的任何返回值或异常。
基本上,finally 子句用于确保资源的正确释放。但是,如果在 finally 块内引发异常,它会消耗来自 try-catch 块的任何返回值或异常。
【解决方案3】:
您可以手动执行此操作,但这有点像 PITA。
public class ExceptionException
{
public static void main( String[] args )
throws Exception
{
Exception saved = null;
try {
throw new Exception( "A" );
} catch( Exception ex ) {
saved = ex;
} finally {
try {
throw new Exception( "B" );
} catch( Exception ex ) {
if( saved != null )
ex.addSuppressed( saved );
}
}
}
}
正如 rgettman 所说,JLS 表示从 finally 子句抛出的异常通常会导致其他异常被遗忘。道德:尽量不要从 finally 子句中抛出异常。