AutoCloseable的close方法抛出exception是否有意义? 应如何处理?

在C#中,在IDisposableDispose方法中抛出exception被认为是不好的做法 。

相比之下,在java中, AutoCloseableclose方法允许抛出任何exception并强制调用者以某种方式处理它。 但如果发生这种情况,合理预期的调用者会怎样做? 这表明关闭资源的尝试以某种方式失败了。 那么用户在继续之前是否必须尝试再次关闭资源,可能是某种指数退避?

看起来涉及资源的每个操作(包括隐式close()调用)都被视为try {}块的一部分。 即使在技术/语法上思考,资源也会在{}括号之外提到。

这意味着如果在close()期间抛出IOException,它将被与您的try相关联的一些catch()子句捕获(或者它将向上传播)。

关于可能需要抛出exception的原因 :close()可能导致flush(),flush()可能导致write(),而write()可能会失败。

AutoCloseable的设计是Java检查exception的结果。 有些实现只需要能够抛出已检查的exception,因此需要throws Exception 。 但是, 实现应声明抛出更多特定类型 (如果有):

虽然声明此接口方法抛出Exception ,但强烈建议实现者声明close方法的具体实现以抛出更具体的exception,或者如果close操作不能失败则不抛出任何exception。

如果有办法避免exception,你不应该抛出exception,但你不能总是避免它。 例如,当关闭具有未刷新数据的BufferedOutputStream时,缓冲流有两个选项; 忽略未写入的数据并关闭或将其写入流,这可能导致抛出exception。

因为Java的设计者能够在实现他们自己的try-with-resourcesfunction之前看到.NET using块中的清理 – exception处理引起的问题,所以他们能够改进它。 在.NET中, Dispose块的作者在吞下任何发生的exception之间经常面临令人不快的选择,从而错误地让调用程序认为一切正常,或者让exception以Dispose方式渗透出来以消除任何证据任何先前的例外。 幸运的是,Java避免了这个问题。

如果try-with-resources块正常成功并且close也正常成功,则外部代码会正常查看所有内容。 如果try部分发生exception但是正常close成功,则外部代码将看到try-blockexception。 如果try正常完成但close抛出,外部代码将看到closeexception。 如果try抛出,但也close也抛出,那么外部代码将看到tryexception,但也能够检索close内发生的任何exception(如果多个嵌套的try-with-resources在close期间抛出exception,则所有抛出的exception将是可用于外部代码)。

因此,与.NET设计不同,它常常迫使作者扼杀Dispose抛出的一些潜在严重的exception,Java的设计倾向于在任何时候出现足够错误的情况下抛出exception,以致不应该让调用者相信一切都很好。