7

我有一个 Java 类,它在内部拥有一个 Closeable 资源。这意味着我的类还实现了 Closeable 接口并在其自己的 close() 方法中关闭了内部资源。

我的类在关闭的预期行为是什么,通常是 Java 中的任何已关闭对象?我看到该对象处于失效状态,其内部已关闭,但客户端仍对其有引用。IMO 访问它是一个编程错误,但错误会不时发生,所以即使在这种情况下,行为也应该是合理的......

我是不是该?

  • 在所有方法调用上抛出异常,例如:IllegalState
  • 闭上眼睛就像什么都没发生一样,让异常从关闭的资源中通过?

什么是规范的 Java 方式?

4

3 回答 3

5

在关闭内部资源后尝试访问内部资源时应该抛出异常,IllegalStateException 就可以了。值得注意的一件事是,您可以在 try-with-resources 中使用 Closeable,以进一步确保一旦对象超出范围,它就会关闭。

于 2020-04-15T13:35:03.577 回答
3

什么是规范的 Java 方式?

首先,我们看一下close()方法的javadoc:

关闭此流并释放与其关联的任何系统资源。如果流已经关闭,则调用此方法无效。

因此,对于该方法,您的选项的答案是“以上都不是” close()。您不会抛出异常,也不会让已关闭资源的异常通过。如果它已关闭,则调用必须是 NOOP。

现在,让我们看一下其中的一些Closeable类:

  • FileInputStream.read()

    IOException如果发生 I/O 错误,则抛出。

    这包括“文件关闭”。

    这适用于所有 InputStream/OutputStream/Reader/Writer I/O 类。

  • FileSystem.close()

    关闭文件系统后,通过此类定义的方法或与此文件系统关联的对象对文件系统的所有后续访问,throw ClosedFileSystemException。如果文件系统已经关闭,则调用此方法无效。

  • Formatter.close()

    尝试ioException()在此格式化程序关闭后调用除此格式化程序之外的任何方法将导致FormatterClosedException.

  • URLClassLoader.findClass(name)

    ClassNotFoundException如果找不到类,或者加载器已关闭,则抛出。

结论:所有方法(除了close())都会抛出异常,尽管不是IllegalStateException

IllegalStateException如果你愿意,你当然可以使用。

于 2020-04-15T13:55:58.667 回答
2

只需使用 close 方法看一下可能最常用的接口之一java.sql.Connection

这里抛出异常:

SQLException if a database access error occurs or this method is called on a closed connection

这基本上是有道理的:如果调用一个close方法,开发人员会心甘情愿地关闭任何对象(Connection, Socket, Stream, ...),因此,正如您已经说过的,它处于失效状态。如果开发人员现在尝试在关闭的对象上调用某个函数,他应该会得到一个错误,因此这里唯一正确的做法是异常。

于 2020-04-15T13:42:15.797 回答