为什么当从finally抛出异常时,Java不支持从try/catch lost中检索异常?



在Java 7中,该特性被添加到(通过getSuppressed())从try-with-resources语句的隐式finally块抛出的get异常。

似乎仍然没有一种方法(据我所知)做相反的事情-当有一个显式的finally块并抛出异常时,掩盖了从try/catch抛出和挂起的异常。

为什么Java不提供通过类似于getSuppressed()的机制来获得这些隐藏/丢失异常的功能?

似乎这个功能的实现将类似于getSuppressed()或链式异常中使用的,并且提供的好处将非常有用,但它继续在每个版本中被遗漏。

通过类似于getSuppressed()的方法调用使这些被屏蔽的异常对程序员可用会有什么危险?

(如果这个功能已经存在,我只是无能为力,提前道歉。)

抑制功能不限于使用资源进行尝试,您可以在类似的情况下使用它。例如,它为其他情况提供的。

try-with-resources将关闭资源的逻辑置于幕后,因此您无法在自己的代码中直接访问处理过程中发生的任何异常。所以他们添加了"抑制"的东西,这样他们就可以在幕后代码中使用它。

但聪明的是,他们没有只是让它可以在那里使用。你可以自己使用,通过Throwable#addSuppressed

你可以在JLS§14.20.3.1给出的伪代码示例中看到这一点;下面是它的真实代码版本:

{
    SomeResource someResource = null;
    Throwable primaryException = null;
    try {
        someResource = /*...get the resource...*/;
        /*...do something...*/
    }
    catch (Throwable t) {
        primaryException = t;
        throw t;
    }
    finally {
        if (someResource != null) {
            if (primaryException != null) {
                // Dealing with a primary exception, close the resource
                // and suppress any exception resulting
                try {
                    someResource.close();
                }
                catch (Throwable suppressed) {
                    primaryException.addSuppressed(suppressed);
                }
            }
            else {
                // Not dealing with a primary exception, close the
                // resource without suppressing any resulting exception
                someResource.close();
            }
        }
    }
}

注意不同的行为(在try中使用异常A,在finally中使用异常B):

try-with-resources异常中a抑制异常b
在正常的try异常中,B屏蔽了异常a。

如果你想要向后兼容(你总是想要它),你需要让B抑制a,但这与try-with-resources的作用完全相反(实际上,与大多数开发人员想要的相反)。

作为一种解决方案,您可以使用Oracle博客中关于try-with-resources如何工作的(稍微修改)代码:

Exception ex;
try {
    doWork();
} catch (Exception e) {
    ex = e;
    throw(e);
} finally {
    try {
        doFinally();
    } catch (Exception e) {
        if (ex != null) {
            ex.addSuppressed(e);
        } else {
            throw(e);
        }
    }
}

如果你想让finally异常抑制初始异常,显然要把throw移出初始catch。

相关内容

  • 没有找到相关文章

最新更新