For a number of years now I have been unable to get a decent answer to the following question: why are some developers so against checked exceptions? I have had numerous conversations, read things on blogs, read what Bruce Eckel had to say (the first person I saw speak out against them).
I am currently writing some new code and paying very careful attention to how I deal with exceptions. I am trying to see the point of view of the "we don't like checked exceptions" crowd and I still cannot see it.
Every conversation I have ends with the same question going unanswered... let me set it up:
In general (from how Java was designed),
- Error is for things that should never be caught (VM has a peanut allergy and someone dropped a jar of peanuts on it)
- RuntimeException is for things that the programmer did wrong (programmer walked off the end of an array)
- Exception (except RuntimeException) is for things that are out of the programmer's control (disk fills up while writing to the file system, file handle limit for the process has been reached and you cannot open any more files)
- Throwable is simply the parent of all of the exception types.
A common argument I hear is that if an exception happens then all the developer is going to do is exit the program.
Another common argument I hear is that checked exceptions make it harder to refactor code.
For the "all I am going to do is exit" argument I say that even if you are exiting you need to display a reasonable error message. If you are just punting on handling errors then your users won't be overly happy when the program exits without a clear indication of why.
For the "it makes it hard to refactor" crowd, that indicates that the proper level of abstraction wasn't chosen. Rather than declare a method throws an IOException, the IOException should be transformed into an exception that is more suited for what is going on.
I don't have an issue with wrapping Main with catch(Exception) (or in some cases catch(Throwable) to ensure that the program can exit gracefully - but I always catch the specific exceptions I need to. Doing that allows me to, at the very least, display an appropriate error message.
The question that people never reply to is this:
If you throw RuntimeException subclasses instead of Exception subclasses then how do you know what you are supposed to catch?
If the answer is catch Exception then you are also dealing with programmer errors the same way as system exceptions. That seems wrong to me.
If you catch Throwable then you are treating system exceptions and VM errors (and the like) the same way. That seems wrong to me.
If the answer is that you catch only the exceptions you know are thrown then how do you know what ones are thrown? What happens when programmer X throws a new exception and forgot to catch it? That seems very dangerous to me.
I would say that a program that displays a stack trace is wrong. Do people who don't like checked exceptions not feel that way?
So, if you don't like checked exceptions can you explain why not AND answer the question that doesn't get answered please?
Edit: I am not looking for advice on when to use either model, what I am looking for is why people extend from RuntimeException because they don't like extending from Exception and/or why they catch an exception and then rethrow a RuntimeException rather than add throws to their method. I want to understand the motivation for disliking checked exceptions.
The good proves that Checked Exception are not needed are:
I was happy if java would provide me with a choice what to use, when working with core libs, like I/O. Like provides two copies of same classes - one wrapped with RuntimeEception. Then we can compare what people would use. For now, though, many people would better go for some framework on top on java, or different language. Like Scala, JRuby whatever. Many just believe that SUN was right.
SNR
Firstly, checked exceptions decrease the "signal-to-noise ratio" for the code. Anders Hejlsberg also talks about imperative vs declarative programming which is a similar concept. Anyway consider the following code snippets:
Update UI from non UI-thread in Java:
Update UI from non UI-thread in C#:
Which seems a lot clearer to me. When you start to do more and more UI work in Swing checked exceptions start to become really annoying and useless.
Jail Break
To implement even the most basic of implementations, such as Java's List interface, checked exceptions as a tool for design by contract fall down. Consider a list that is backed by a database or a filesystem or any other implementation that throws a checked exception. The only possible implementation is to catch the checked exception and rethrow it as an unchecked exception:
And now you have to ask what is the point of all that code? The checked exceptions just add noise, the exception has been caught but not handled and design by contract (in terms of checked exceptions) has broken down.
Conclusion
I blogged about this previously.
The article Effective Java Exceptions explains nicely when to use unchecked and when to use checked exceptions. Here are some quotes from that article to highlight the main points:
(SO doesn't allow tables, so you might want to read the following from the original page...)
The thing about checked exceptions is that they are not really exceptions by the usual understanding of the concept. Instead, they are API alternative return values.
The whole idea of exceptions is that an error thrown somewhere way down the call chain can bubble up and be handled by code somewhere further up, without the intervening code having to worry about it. Checked exceptions, on the other hand, require every level of code between the thrower and the catcher to declare they know about all forms of exception that can go through them. This is really little different in practice to if checked exceptions were simply special return values which the caller had to check for. eg.[pseudocode]:
Since Java can't do alternative return values, or simple inline tuples as return values, checked exceptions are are a reasonable response.
The problem is that a lot of code, including great swathes of the standard library, misuse checked exceptions for real exceptional conditions that you might very well want to catch several levels up. Why is IOException not a RuntimeException? In every other language I can let an IO exception happen, and if I do nothing to handle it, my application will stop and I'll get a handy stack trace to look at. This is the best thing that can happen.
Maybe two methods up from the example you want to catch all IOExceptions from the whole writing-to-stream process, abort the process and jump into the error reporting code; in Java you can't do that without adding ‘throws IOException’ at every call level, even levels that themselves do no IO. Such methods should not need to know about the exception handling; having to add exceptions to their signatures:
And then there's plenty of just ridiculous library exceptions like:
When you have to clutter up your code with ludicrous crud like this, it is no wonder checked exceptions receive a bunch of hate, even though really this is just simple poor API design.
Another particular bad effect is on Inversion of Control, where component A supplies a callback to generic component B. Component A wants to be able to let an exception throw from its callback back to the place where it called component B, but it can't because that would change the callback interface which is fixed by B. A can only do it by wrapping the real exception in a RuntimeException, which is yet more exception-handling boilerplate to write.
Checked exceptions as implemented in Java and its standard library mean boilerplate, boilerplate, boilerplate. In an already verbose language this is not a win.
The programmer needs to know all of the exceptions that a method may throw, in order to use it correctly. So, beating him over the head with just some of the exceptions does not necessarily help a careless programmer avoid errors.
The slim benefit is outweighed by the burdensome cost (especially in larger, less flexible code bases where constantly modifying the interface signatures is not practical).
Static analysis can be nice, but truly reliable static analysis often inflexibly demands strict work from the programmer. There is a cost-benefit calculation, and the bar needs to be set high for a check that leads to a compile time error. It would be more helpful if the IDE took on the role of communicating which exceptions a method may throw (including which are unavoidable). Although perhaps it would not be as reliable without forced exception declarations, most exceptions would still be declared in documentation, and the reliability of an IDE warning is not so crucial.
To attempt to address just the unanswered question:
The question contains specious reasoning IMHO. Just because the API tells you what it throws doesn't mean you deal with it in the same way in all cases. To put it another way, the exceptions you need to catch vary depending on the context in which you use the component throwing the exception.
For example:
If I'm writing a connection tester for a database, or something to check the validity of a user entered XPath, then I'd probably want to catch and report on all checked and unchecked exceptions that are thrown by the operation.
If, however, I am writing a processing engine, I will likely treat an XPathException (checked) in the same way as an NPE: I would let it run up to the top of the worker thread, skip the rest of that batch, log the issue (or send it to a support department for diagnosis) and leave feedback for the user to contact support.