问题
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