代码之家  ›  专栏  ›  技术社区  ›  Ori Marko

Java终于知道在没有任何变量的情况下抛出的异常[duplicate]

  •  0
  • Ori Marko  · 技术社区  · 7 年前

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

    有没有更优雅的方式来做这个?也许一个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
    }
    

    显然,还有许多其他类似的kludge可能涉及将异常保存为成员变量、从方法返回它等。。。但我想找更优雅一点的。

    也许是像 Thread.getPendingException() 或者类似的东西?对于这个问题,有没有其他语言的优雅解决方案?

    another question 这引发了一个有趣的问题。

    0 回复  |  直到 9 年前
        1
  •  12
  •   zb226 Steven Lizarazo    9 年前

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

    不能同时传播多个异常。

        2
  •  6
  •   Triynko    17 年前

    我不使用布尔标志,而是存储对异常对象的引用。 这样,您不仅可以检查是否发生异常(如果没有异常发生,对象将为null),而且如果发生异常,您还可以访问finally块中的异常对象本身。您只需记住在所有catch块中设置error对象(iff返回错误)。

    我认为这是一个缺少的C语言特性,应该添加进来。 finally块应该支持对基异常类的引用,类似于catch块对它的支持方式,以便finally块可以使用对传播异常的引用。这应该是 编译器的一项简单任务 为我们省去了工作 手动 创建局部异常变量并 回忆 犯错误 在不重新抛出错误时设置异常变量(记住,我们只想让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块中使用异常的原因是,如果finally块确实捕捉到了它自己的异常,那么 通过引发新错误覆盖主异常(错误) 或者只是 ,它可以将错误作为附加数据添加到原始错误中。

        3
  •  2
  •   Joel Coehoorn    18 年前

        4
  •  2
  •   gedevan    18 年前

    使用日志记录。。。

    try {   
       stream.write(buffer); 
    } catch(IOException ex) {
        if (LOG.isErrorEnabled()) { // You can use log level whatever you want
            LOG.error("Something wrong: " + ex.getMessage(), ex);
        }
        throw ex;
    } finally {   
        if (stream != null) {
            try {
                stream.close();
            } catch (IOException ex) {
                if (LOG.isWarnEnabled()) {
                    LOG.warn("Could not close in finally block", ex);
                }
            }
        }
    }
    
        5
  •  1
  •   supercat    15 年前

    1. 如果没有任何东西“最终”捕获异常,则会从原始异常的位置触发未经处理的异常陷阱。尤其是在调试过程中,由于调试过程中的信息最终被排除在陷阱之外,特别是在调试过程中。

    因为vb不支持这个特性,所以编写一个vb包装器来实现C语言中的代码(例如,给定一个MethodInvoker和一个Action(例外),在“Try”中执行MethodInvoker,在“Finally”中执行Action。

    一个有趣的怪癖:对于Catch来说,当看到一个最终被Finally子句异常覆盖的异常是可能的。在某些情况下,这可能是件好事;在另一些情况下,这可能会令人困惑。无论如何,这都是值得注意的。