If you ever get one of those interview questions along the lines of "What DON'T you like about Java?", I would hope that checked exceptions are at the top of your list. I think no other, ahem, feature, of Java has caused more code bloat, more problems, and less stability than checked exceptions. Java was the first main-stream language to include this concept (to my knowledge), the only (widely used) programming language that has it, and I strongly hope it will be the last programming language to include it.
Checked exceptions cause a lot of grief. They often pollute APIs: look at how the JDBC API plays "cover your ass" by making every single method throws JDBCException
regardless of which methods do any work that could possibly fail. At best, checked exceptions make sense only when there is a clear and documented way to recover from the exception (such as waiting and retrying the failed operation). In many cases, a simple boolean, indicating success or failure, would be much better than an exception, and accomplish the same goals with far less cost.
Checked exception's also encourage another terrible pattern: exception swallowing. "What do I do with this here MyAPIIsBrokenException? Well Eclipse just inserts code to print out the stack trace, so that's good enough." Thus real errors get discarded, and code that should break during testing slips through the cracks, causing nasty runtime failures and ominous messages to the console.
Really, what can you do with an exception? Either handle it locally and immediately, or wrap it in another exception, usually RuntimeException, and rethrow it ... but that approach is only effective if some higher layer does a good job of reporting the entire stack of exceptions, the way Tapestry does. More often, the exception just percolates up to a top-level loop and spews out a few hundred lines of glop onto the console or log.
I think part of the proof that checked exceptions are simply unworkable is the way throws Exception
is creeping into standard APIs, such as the ones specified in project Coin (I'm thinking of Autocloseable). And what is the semantic value of throws Exception
? It's useless ... because you are either going to log that exception to the console or wrap it in a new RuntimeException and re-throw it. So the authors of Autoocloseable have simply shifted work onto your lap (you get to write the code to catch it and rethrow it) when if they simply omitted the throws clause, and documented that "close() methods may throw a runtime exception" you could get the exact same effect, but write much less code.
I've also seen that checked exceptions have been a factor in the delays for JDK 8 Lambdas, complicating that specification much further than it needed to be, and forcing new and odder syntax into the language to accompany it.
Meanwhile, post-Java JVM languages ... including Groovy, Fantom, and Clojure ... simply ignore checked exceptions; which is easy enough to do as they are almost entirely a fiction of the Java compiler in the first place. You can write try...catch blocks in these languages, but there's no pressing need to, and application stability ends up being higher than in traditional Java code.
It is unfortunate that of all the ideas that Gosling, Joy, and folks had at the dawn of the Java language, they deferred ones we've really been missing (such as reified types and lambdas) and included truly experimental features, such as checked exceptions. But that's just hind-sight and second-guessing. The real tragedy is that, unlike (for example) JavaScript, with Java you can't just use the good parts. Instead, Java snares you with an almost irrational compulsion to preserve the early mistakes in the language, forever.