CheckedExceptions force us to propagate exception type information up all potential call chains. In theory this is good because we then know all the kinds of exception that any given method may throw and then can handle those we care about and propagate those which we do not. In practice, however, it turns out that we almost never actually use this information. Instead, calls that are deep in the stack propagate almost all the exceptions they encounter while a few calls near the top of the call stack handle most exceptions in a uniform manner. In the meantime we are paying a very high price to maintain all of this information that never gets used. Every time a method is changed in such a way that it throws a new kind of exception all of the methods that depend on it, directly or indirectly, must be edited to either catch or explicitly propagate the new type of exception.
This difficulty has lead some to abandon CheckedExceptions and some to avoid exceptions entirely. There is no need for either of these measures, however. CheckedExceptions do offer one valuable piece of information: they tell us whether a method is allowed to throw an exception or not. This is important because there are some situations where it is impossible to write correct code using operations that can throw an exception. For instance, a CommitCantThrow? because if it did the data would be left in an inconsistent state. The "throws" clause gives us a way to tell the difference between those methods that might throw an exception and those that are guaranteed not to.
It would be nice if there were a "doesn't throw" clause that we could use to mark those special methods that can't propagate exceptions, but we don't have that.
Therefore:
Assume that any method may, at some time, propagate an exception. Account for this by adding a "throws" clause to every method you write unless you mean to explicitly guarantee that a method will never propagate an exception and will never be edited in such a way as to cause it to propagate an exception. Once a method has been written without a "throws" clause make it a practice never to add one unless ALL clients have been checked to ensure that they do not require the method to be exception free.
Avoid dependency problems by declaring all methods to throw "Exception". Since all CheckedExceptions have Exception somewhere above them in the class hierarchy the compiler will accept this declaration regardless of which exceptions the method actually propagates. More importantly the compiler will continue to accept it regardless of changes made to other methods which may indirectly cause your method to propagate a new type of exception.
How is that a good thing? (If methods are changed to throw new exceptions, you have no reminder to check the callers to see if they need to account for the new exceptions.)
This page mirrored in JavaIdioms as of April 29, 2006