Is it meaningful for AutoCloseable's close method to throw an exception? How should this be handled?

删除回忆录丶 提交于 2020-01-11 10:04:29

问题


In C#, it is considered bad practice to throw exceptions in the Dispose method of an IDisposable.

By contrast, in java the close method of AutoCloseable allows any Exception whatsoever to be thrown and forces the caller to handle it somehow. But what is the caller reasonably expected to do if this happens? This suggests that the attempt to close the resource failed somehow. So does the user have to try to close the resource again before continuing, perhaps with some sort of exponential backoff?


回答1:


It looks like every operation involving the resources, including the implicit close() invocation, is considered part of the try{} block. Even thought technically/syntactically, the resources are mentioned outside the {} braces.

Meaning that if an IOException gets thrown during the close(), it will get caught by some catch() clause associated with your try (or it will propagate up).

About the reason why exceptions might need to be thrown : close() might cause flush(), flush() might cause write()s, and write()s might fail.




回答2:


The design of AutoCloseable is a result of Java's checked exceptions. Some implementations simply have to be able to throw checked exceptions, and so throws Exception is needed. However, implementations should declare more specific types thrown (if any):

While this interface method is declared to throw Exception, implementers are strongly encouraged to declare concrete implementations of the close method to throw more specific exceptions, or to throw no exception at all if the close operation cannot fail.

You shouldn't throw exceptions if there's a way of avoiding it, but you can't always avoid it. For example, when closing a BufferedOutputStream with unflushed data, the buffered stream has two options; ignoring the unwritten data and close, or writing it to the stream, which can cause exceptions to be thrown.




回答3:


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.



来源:https://stackoverflow.com/questions/26459988/is-it-meaningful-for-autocloseables-close-method-to-throw-an-exception-how-sho

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