【问题标题】: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 块“突然完成”SfinallyException,“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 子句中抛出异常。

        【讨论】: