Because Java's designers were able to see the issues that arose with cleanup-exception handling in .NET's using
blocks before implementing their own try-with-resources feature, they were able to improve upon it. In .NET, the author of a Dispose
block is often faced with an unpleasant choice between swallowing any exceptions which occur, thus erroneously letting the calling program believe everything is fine, or letting exceptions percolating out from Dispose
in such fashion as to obliterating any evidence of any previous exception. Fortunately, Java avoids that issue.
If a try-with-resources block succeeds normally and the close
also succeeds normally, then the outside code sees everything as normal. If an exception occurs in the try
portion but the close
succeeds normally, the outside code will see the try-block exception. If the try
completes normally but the close
throws, the outside code will see the close
exception. And if try
throws, but close
also throws, then outside code will see the try
exception but also be able to retrieve any exception that occurred within close
(and if multiple nested try-with-resources throw exceptions during close
, all thrown exceptions will be available to the outside code).
Consequently, unlike the .NET design which often compels authors to stifle some potentially-serious exceptions thrown by Dispose
, Java's design favors having close
throw an exception any time something goes sufficiently wrong that the caller shouldn't be allowed to believe that everything's fine.