是否可以检测在我进入最终块之前是否发生了异常?

2022-09-02 01:40:53

在Java中,有没有一种优雅的方法来检测在运行finally块之前是否发生了异常?在处理“close()”语句时,通常需要在最后的块中进行异常处理。理想情况下,我们希望同时维护这两个异常并将它们传播起来(因为它们都可能包含有用的信息)。我能想到的唯一方法是在 try-catch-final 作用域之外有一个变量来保存对引发异常的引用。然后将“已保存”异常与最终块中发生的任何异常一起传播。

有没有更优雅的方法来做到这一点?也许API调用会揭示这一点?

以下是我正在谈论的一些粗略代码:

Throwable t = null; 
try {   
   stream.write(buffer); 
} catch(IOException e) {
    t = e;   //Need to save this exception for finally
    throw e;
} finally {   
    try {
       stream.close();   //may throw exception
   } catch(IOException e) {
      //Is there something better than saving the exception from the exception block?
      if(t!=null) {
         //propagate the read exception as the "cause"--not great, but you see what I mean.
         throw new IOException("Could not close in finally block: " + e.getMessage(),t);
      } else {
         throw e;  //just pass it up
      }    
   }//end close
}

显然,还有许多其他类似的笨拙可能涉及将异常保存为成员变量,从方法返回它等。但我正在寻找一些更优雅的东西。

也许是类似或类似的东西?就此而言,其他语言是否有优雅的解决方案?Thread.getPendingException()

这个问题实际上是从另一个问题中的评论中产生的,该问题提出了一个有趣的问题。


答案 1

您关于在 try/catch/final 范围之外设置变量的想法是正确的。

不能同时传播多个异常。


答案 2

我不会使用布尔标志,而是存储对 Exception 对象的引用。这样,您不仅可以检查是否发生了异常(如果未发生异常,则对象将为 null),而且如果确实发生了异常,您还可以访问最终块中的异常对象本身。你只需要记住在所有捕获块中设置错误对象(如果重新抛出错误)。

我认为这是应该添加的缺少的C#语言功能。finally 块应支持对基 Exception 类的引用,类似于 catch 块支持它的方式,以便对传播异常的引用可用于 finally 块。对于编译器来说,这将是一项简单的任务为我们节省了手动创建局部 Exception 变量并记住在重新引发错误之前手动设置其值的工作,并防止我们在不重新引发错误时错误地设置 Exception 变量(请记住,这只是我们想要对 finally 块可见的未捕获的异常)。

finally (Exception main_exception)
{
    try
    {
        //cleanup that may throw an error (absolutely unpredictably)
    }
    catch (Exception err)
    {
        //Instead of throwing another error,
        //just add data to main exception mentioning that an error occurred in the finally block!
        main_exception.Data.Add( "finally_error", err );
        //main exception propagates from finally block normally, with additional data
    }
}

如上所述...我希望在 finally 块中提供异常的原因是,如果我的最终块确实捕获了自己的异常,那么它不是通过抛出新错误(bad)或只是忽略错误(也是 bad)来覆盖主要异常,而是可以将错误作为附加数据添加到原始错误中。


推荐