I'm looking through the Java source code, and have found something interesting which is indicative of the IOException
reason. InputStream
is an abstract class. We therefore can't predict the kind of input which will be closed, so it's good to keep information flowing.
Whatever code uses that input stream needs to be able to throw an IOException
, because there is a chance that closing the input stream may fail. If it fails, whatever's using the implementation needs to know about it, because there's a good chance it needs to be handled.
It's important to understand the layout of the Exception structure in Java. Every exception, of course, extends Exception
. However, there are also broader categories of exceptions: java.lang.IOException
is one of these, and covers all possible input/output exceptions. When we say there has been an I/O error, we're referencing anything which falls under IOException
. As a result, many exceptions extends this one, e.g. FileNotFoundException
, EOFException
, etc. as it's important to have a broad, overarching exception to manage these.
As a result, any IO class will need to be able to throw any of the various IOExceptions on close. close()
therefore must throw IOException
- this gives its implementation the ability to throw any of the extensions of IOException
as well. This is why close()
throws IOException
- exceptions are inherited, and you need to be able to any of the IOExceptions when closing a stream.
Here are a couple scenarios worth noting:
- You can't close an IOStream twice, though this generally doesn't throw an exception if you do
- The content becomes inaccessible (e.g. a disk was unmounted) (The
close()
is actually critical for the operating system, as it needs to have an indicator of when the file is no longer busy)
- The generic source has closed
- Any generic failure not covered by all other subclasses of
IOException
(e.g. FileNotFoundException
)
You can check what caused an IOException
by running Exception.getMessage()
.