【问题标题】:Is it meaningful for AutoCloseable's close method to throw an exception? How should this be handled?AutoCloseable的close方法抛出异常有意义吗?这应该如何处理?
【发布时间】:2014-12-15 02:25:47
【问题描述】:

在 C# 中,在 IDisposableDispose 方法中抛出异常是 considered 错误 practice

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

【问题讨论】:

标签: java c# exception idisposable autocloseable


【解决方案1】:

因为 Java 的设计人员能够在实现自己的 try-with-resources 功能之前看到 .NET 的 using 块中的清理异常处理出现的问题,所以他们能够对其进行改进。在 .NET 中,Dispose 块的作者经常面临一个令人不快的选择,要么吞下发生的任何异常,从而错误地让调用程序相信一切正常,要么让异常从 Dispose 渗出,以如下方式消除任何先前例外的任何证据。幸运的是,Java 避免了这个问题。

如果 try-with-resources 块正常成功并且close 也正常成功,则外部代码认为一切正常。如果try 部分发生异常但close 正常成功,则外部代码将看到try-block 异常。如果try 正常完成但close 抛出,外部代码将看到close 异常。如果try 抛出,但close 也抛出,那么外部代码将看到try 异常,但也能够检索在close 中发生的任何异常(并且如果多个嵌套的try-with-resources 抛出异常在close 期间,所有抛出的异常都将可供外部代码使用)。

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

【讨论】:

  • 这些在 Java 中被称为“被抑制的异常”,Throwable 有它们的访问器。请参阅docs.oracle.com/javase/tutorial/essential/exceptions/… 的“抑制的异常”部分
  • @SensorSmith:随意编辑脚注等细节。我的 Java 经验早于 try-with-resources,所以我宁愿这样的脚注由比我自己更有资格的人写。
【解决方案2】:

AutoCloseable 的设计是 Java 已检查异常的结果。一些实现只需要能够抛出已检查的异常,因此需要throws Exception。但是,implementations should declare more specific types thrown(如果有):

虽然此接口方法声明为抛出 Exception,但强烈鼓励实现者声明 close 方法的具体实现以抛出更具体的异常,或者在以下情况下不抛出任何异常关闭操作不能失败。

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

【讨论】:

    【解决方案3】:

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

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

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

    【讨论】:

    • 如果我尝试过 (BufferedReader br = new BufferedReader(new FileReader(path))) { return br.readLine(); } 和br.close() 抛出异常,那么我将无法在必须处理异常的地方再次尝试关闭资源。这似乎表明没有必要再次尝试关闭资源。
    猜你喜欢
    • 1970-01-01
    • 2018-12-08
    • 2011-10-13
    • 2014-11-15
    • 1970-01-01
    • 1970-01-01
    • 2016-08-14
    • 1970-01-01
    • 2013-05-20
    相关资源
    最近更新 更多