Videos
Motivating example: I have an HTTP client whose sole purpose is to produce a single InputStream. The HTTP client should be closed as soon as the InputStream is closed. Is there a way to subscribe the HTTP client's close() method to the stream's?
The real problem is doing this generically. I can create a subclass of InputStream overriding close() and add httpClient.close(), but maybe tomorrow I'm facing the same problem but instead of an Http client it's a file handle, or I need to dispose of multiple resources B, C, D when A closes, and so on. Being able to "subscribe" a closeable resource to another would be ideal, but the API doesn't seem to support this.
You should throw an exception when trying to access the internal resource after it has been closed, an IllegalStateException would be fine. One thing worth noting is you can use your Closeable in a try-with-resources to further ensure that once the object falls out of scope it is closed.
What is the canonical Java way?
First, let's look at the javadoc of the close() method:
Closes this stream and releases any system resources associated with it. If the stream is already closed then invoking this method has no effect.
So the answer to your options is "none of the above" for the close() method. You don't throw an exception, and you don't let exceptions through from the closed resource. If it has been closed, the call must be a NOOP.
Now, let's have a look at some of the Closeable classes:
FileInputStream.read()Throws
IOExceptionif an I/O error occurs.That includes "file closed".
That goes for all the InputStream/OutputStream/Reader/Writer I/O classes.
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 aFormatterClosedException.URLClassLoader.findClass(name)Throws
ClassNotFoundExceptionif the class could not be found, or if the loader is closed.
Conclusion: All the methods (except close()) throw exceptions, though not IllegalStateException.
You can of course use IllegalStateException if you want.