封闭资源在 java 中应该如何表现?

How should a closed resource behave in java?

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

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

我应该吗?

规范的 Java 方式是什么?

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

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

这里抛出异常:

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

这基本上是有意义的:如果调用 close 方法,开发人员 愿意 关闭对象(ConnectionSocket, Stream, ...),因此正如您已经说过的那样,它处于失效状态。如果开发人员现在试图在关闭的对象上调用某个函数,他应该会得到一个错误,因此异常是这里唯一正确的做法。

What is the canonical Java way?

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

Closes this stream and releases any system resources associated with it. If the stream is already closed then invoking this method has no effect.

因此,对于 close() 方法,您的选项的答案是 "none of the above"。您不会抛出异常,也不会让异常从已关闭的资源中通过。如果已经关闭,则调用必须是NOOP。

现在,让我们来看看一些 Closeable 类:

  • FileInputStream.read()

    Throws IOException if an I/O error occurs.

    其中包括 "file closed"。

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

  • FileSystem.close()

    After a file system is closed then all subsequent access to the file system, either by methods defined by this class or on objects associated with this file system, throw ClosedFileSystemException. If the file system is already closed then invoking this method has no effect.

  • Formatter.close()

    Attempting to invoke any methods except ioException() in this formatter after it has been closed will result in a FormatterClosedException.

  • URLClassLoader.findClass(name)

    Throws ClassNotFoundException if the class could not be found, or if the loader is closed.

结论:所有方法(close()除外)都会抛出异常,但不会IllegalStateException

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