Why does Java not support retrieval of exceptions from try/catch lost when an exception is thrown from finally?

不羁岁月 提交于 2019-12-12 11:19:57

问题


In Java 7, the feature was added to (via getSuppressed()) get exceptions thrown from the implicit finally block of a try-with-resources statement.

There still doesn't seem to be a way (that I know of) to do the opposite - when there is an explicit finally block and that throws an exception, masking the exceptions thrown and pending from the try/catch.

Why does Java not provide functionality to get these buried/lost exceptions through a mechanism similar to getSuppressed()?

It would seem that the implementation of this functionality would be similar to that used in getSuppressed() or chained exceptions, and the provided benefit would be very useful, yet it continues to be left out of each release.

What would be the danger of making these masked exceptions available to programmers through a method call similar to getSuppressed()?

(Apologies in advance if this functionality already exists and I'm just clueless.)


回答1:


The suppression thing isn't limited to try-with-resources, and you can use it for similar situations yourself. E.g., it is provided for other situations.

try-with-resources puts the logic for closing the resources behind the scenes, so you don't have direct access in your own code to dealing with any exceptions that occur during the process. So they added the "suppression" thing so they could use it in that behind-the-scenes code.

But cleverly, they didn't only make it something that could be used there. You can use it yourself, via Throwable#addSuppressed.

You can see this in the pseudo-code example given in JLS §14.20.3.1; here's a real code version of it:

{
    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();
            }
        }
    }
}



回答2:


Note the different behaviour (Using exception A for the exception in try, exception B in finally):

In a try-with-resources exception A suppresses exception B.
In a normal try exception B masks exception A.

If you want backwards compatibility (And you ALWAYS want it), you need to make B suppress A. But that is the complete opposite of what try-with-resources does (and actually, the opposite of what most developers want).

As a workaround, you can just use the (slightly modified) code that is in the Oracle blog on how try-with-resources works:

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);
        }
    }
}

Obviously move the throw out of the initial catch if you want the finally exception to suppress the initial one.



来源:https://stackoverflow.com/questions/24181489/why-does-java-not-support-retrieval-of-exceptions-from-try-catch-lost-when-an-ex

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!