在C#中,在IDisposable
的Dispose
方法中抛出异常被认为是不良做法(considered)(bad practice)。
相比之下,在Java中,AutoCloseable
的close
方法允许抛出任何异常,并强制调用者以某种方式处理它。但如果发生这种情况,调用者可以合理地期望做什么呢?这表明尝试关闭资源失败了。用户是否需要再次尝试关闭资源,或许使用某种指数退避策略?
在C#中,在IDisposable
的Dispose
方法中抛出异常被认为是不良做法(considered)(bad practice)。
相比之下,在Java中,AutoCloseable
的close
方法允许抛出任何异常,并强制调用者以某种方式处理它。但如果发生这种情况,调用者可以合理地期望做什么呢?这表明尝试关闭资源失败了。用户是否需要再次尝试关闭资源,或许使用某种指数退避策略?
AutoCloseable
的设计是 Java 受检异常的结果。一些实现必须能够抛出受检异常,因此需要 throws Exception
。然而,如果有的话,实现应该声明更具体的异常类型:
虽然这个接口方法被声明为抛出
Exception
,但强烈建议实现者声明close
方法的具体实现抛出更具体的异常,或者如果关闭操作不可能失败,则不抛出任何异常。
如果有避免抛出异常的方法,就不应该抛出异常,但并不总是可以避免。例如,在关闭带有未刷新数据的 BufferedOutputStream
时,缓冲流有两个选项;忽略未写入的数据并关闭,或将其写入流中,这可能会导致抛出异常。
看起来涉及资源的每个操作,包括隐式的close()调用,都被视为try{}块的一部分。即使从技术上/语法上讲,资源是在{}大括号之外提到的。
这意味着如果在close()期间抛出IOException,它将被与您的try相关联的某个catch()子句捕获(或者它将向上传播)。
关于为什么可能需要抛出异常的原因:close()可能会导致flush(),flush()可能会导致write()失败。
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}
并且 br.close()
抛出异常,则我将无法在必须处理该异常的地方再次尝试关闭资源。这似乎表明不需要再次尝试关闭资源。 - George Simms