First, it’s worth noting that Java effectively invented the checked exception (clearly inspired by C++ exception specifications and the fact that C++ programmers typically don’t bother with them). It has been an experiment, which no language since has chosen to duplicate.
Secondly, checked exceptions appear to be an obvious good thing when seen in introductory examples and in small programs. It has been suggested that the subtle difficulties begin to appear when programs start to get large. Of course, largeness usually doesn’t happen overnight; it creeps. Languages that may not be suited for large-scale projects are used for small projects that grow, and at some point we realize that things have gone from manageable to difficult. This is what I’m suggesting may be the case with too much type checking; in particular, with checked exceptions.
The scale of the program seems to be a significant issue. This is a problem because most discussions tend to use small programs as demonstrations. One of the C# designers observed that:
“Examination of small programs leads to the conclusion that requiring exception specifications could both enhance developer productivity and enhance code quality, but experience with large software projects suggests a different result—decreased productivity and little or no increase in code quality.” 
In reference to uncaught exceptions, the CLU creators stated:
“We felt it was unrealistic to require the programmer to provide handlers in situations where no meaningful action can be taken.” 
When explaining why a function declaration with no specification means that it can throw any exception, rather than no exceptions, Stroustrup states:
“However, that would require exception specifications for essentially every function, would be a significant cause for recompilation, and would inhibit cooperation with software written in other languages. This would encourage programmers to subvert the exception-handling mechanisms and to write spurious code to suppress exceptions. It would provide a false sense of security to people who failed to notice the exception.” 
We see this very behavior—subverting the exceptions—happening with checked exceptions in Java.
Martin Fowler (author of UML Distilled, Refactoring, and Analysis Patterns) wrote the following to me:
“...on the whole I think that exceptions are good, but Java checked exceptions are more trouble than they are worth.”
I now think that Java’s important step was to unify the error reporting model, so that all errors are reported using exceptions. This wasn’t happening with C++, because for backward compatibility with C the old model of just ignoring errors was still available. But if you have consistent reporting with exceptions, then the exceptions can be used if desired, and if not, they will propagate out to the highest level (the console or other container program). When Java changed the C++ model so that exceptions were the only way to report errors, the extra enforcement of checked exceptions may have become less necessary.
In the past, I have been a strong believer that both checked exceptions and strong static type checking were essential to robust program development. However, both anecdotal and direct experience with languages that are more dynamic than static have lead me to think that the great benefits actually come from:
- A unified error-reporting model via exceptions, regardless of whether the
programmer is forced by the compiler to handle them.
- Type checking, regardless of when it takes place. That is, as long as
proper use of a type is enforced, it doesn’t matter if it happens at
compile time or run time.
I’ve already been told by some that what I say here constitutes blasphemy, and by uttering these words my reputation will be destroyed, civilizations will fall, and a higher percentage of programming projects will fail. The belief that the compiler can save your project by pointing out errors at compile time runs strong, but it’s even more important to realize the limitation of what the compiler is able to do; in Chapter 15, I emphasize the value of an automated build process and unit testing, which give you far more leverage than you get by trying to turn everything into a syntax error. It’s worth keeping in mind that:
A good programming language is one that helps programmers write good programs. No programming language will prevent its users from writing bad programs.
In any event, the likelihood of checked exceptions ever being removed from Java seems dim. It would be too radical of a language change, and proponents within Sun appear to be quite strong. Sun has a history and policy of absolute backwards compatibility—to give you a sense of this, virtually all Sun software runs on all Sun hardware, no matter how old. However, if you find that some checked exceptions are getting in your way, or especially if you find yourself being forced to catch exceptions, but you don’t know what to do with them, there are some alternatives.