Do you agree that the designers of Java class java.io.IOException
should have made it an unchecked run-time exception derived from java.lang.RuntimeException<
Probably the vast majority of IO exceptions are recoverable - permissions errors, lack of space on the drive, connection closed, etc, etc. I believe unchecked exceptions are supposed to be used for "there's no reasonable way to recover from this" sorts of situations.
I know it has been 4 years since this question was asked but an UncheckedIOException was added in Java 8.
In a well-designed exception framework, a distinction should be made between exceptions which are to some extent "expected" and those which are not. Java attempts to use checked versus unchecked exceptions for this. By that standard, IOException should be a checked exception.
A fundamental problem, though, is that oftentimes code will be written with a (perhaps reasonable) expectation that a certain exception will not occur, and nothing can usefully be done to handle it if it does. If a method is declared as throwing a particular checked exception, Java allows its caller to ignore the exception if it declares itself as throwing that exception, but there's no means by which a method or code block can specify that certain exceptions from called methods are not expected to occur. A common anti-pattern is:
try
{
methodThatsDeclaredAsThrowingFooExceptionButWont()
}
catch FooException Ex
{
// Never going to happen
}
The apparent assumption is that since the method won't throw FooException and the only reason the catch
is there is to make the compiler happy, there's no reason for the catch
to do anything. Insidious, because if a FooException
does get thrown, for whatever reason, it will go undetected.
An alternative is for a method which calls methodThatsDeclaredAsThrowingFooExceptionButWont to declare itself as throws FooException
or throws Exception
, but that isn't really appropriate either. If a method which is not expected to throw a FooException
does, the system state is apt to be different from what it would be expected when a FooException
is thrown.
For example, suppose one attempts to load a document, but the document-load routine needs to read some non-document-specific translation tables which are supposed to be stored at a fixed location; if that attempt fails, having the IOException
percolate up to the caller would imply that there was a problem loading the document being loaded. If the load-document routine isn't prepared to sensibly handle the possibility that the load-translation-tables routine might fail, such failure shouldn't percolate up the same way as would an IOException
that occurred while actually loading the document.
The proper remedy would not be for IOException
to be an unchecked exception, but rather for there to be a declarative means by which code could indicate that one or more kinds of checked exceptions should not be allowed to percolate out of a certain block from methods called thereby, but should instead be wrapped in some other exception type (e.g. RuntimeException).
I completely disagree. To me the model is correct. A RuntimeException is one which most typically denotes a serious error in the logic of the programming (such as ArrayIndexOutOfBounds, NullPointer, or IllegalArgument) or something that the runtime has otherwise determined really shouldn't be happening (such as SecurityException).
Conversely IOException and its derivatives are exceptions that could reasonably occur during normal execution of a program, and common logic would dictate that either those problems should be dealt with, or at least the programmer should be aware that they can occur. For example with Files if your application logger can't write its data would you rather be forced to catch a potential IOException and recover, or have something that may not be critical to your app bring down the whole JVM because no one thought to catch the unchecked Exception (as you may have guessed, I'll choose the former).
I think that there are many situations in which an IOException is either recoverable, or at the least the programmer should be explicitly aware of the potential so that if it is not recoverable the system might be able to crash more "gently".
As far your thought of if the system can not recover there are always alternatives with a checked exception. You can always have your methods declare it in their throws, throw a runtime exception of their own or crash the JVM violently:
public void doit() throws IOException {
try{
}catch(IOException e){
// try to recover
...
// can't recover
throw e;
}
}
public void doit() {
try{
}catch(IOException e){
// try to recover
...
// can't recover
throw new RuntimeException(e);
}
}
public void doit() {
try{
}catch(IOException e){
// try to recover
...
// OH NO!!!!
System.exit(Constant.UNRECOVERABLE_IO_ERROR);
}
}
No because you can recover from some IOExceptions. Most notable ones are low level indexed reads and writes. If it fails, sometimes you can just retry without harm.
I think it is clever to leave it a checked exception. I regard runtime exceptions as bugs, and this is clearly not the case. Recovery by retry is sometimes possible, and also some IOException messages can be informative to the end user (e.g. no permissions to write, not enough disk space, etc).