This page contains an archived post to the Design Forum (formerly called the Flexible Java Forum) made prior to February 25, 2002.
If you wish to participate in discussions, please visit the new
Posted by Bill Venners on 18 Jun 1998, 10:18 AM
> In general, I agree with the advice to throw meaningful,
> specific subclasses of Exception. However, it's important to
> consider how to do this in a way that allows the code to
> evolve over time without breaking clients. As emphasized in the
> article, the throws clause is an important part of the contract
> between a class and its clients. If a future version of the
> class needs to throw a new type of exception, the clients will
> have to be recompiled.
> A nice solution is used in package java.io. Many methods of
> classes in this package throw IOException, which is actually
> the superclass of numerous exception types. Most clients only
> need to catch the more general IOException, but can handle
> specific exceptions if needed. Future versions of these classes
> may throw new subclasses of IOException without requiring client
> code recompilation.
This is an excellent point, though I have one caveat of
your caveat to offer.
Another good guideline concerning exceptions could be:
Create families of exception types, not just individual
Families, like IOException, give you more flexibility because
clients can just make a catch clause for the base type and
catch the subclass types that exist today, AND their code
won't break if I add another subclass exception to my
throws clause in the future. There superclass catch clause
will catch this new exception.
The caveat I have to this is that I think the whole point of
having checked vs. unchecked exceptions is that checked
exceptions are *supposed* to break the client's code. If a
client doesn't either catch the checked exception or declare
it in its throws clause, that client code won't compile
(i.e. is broken). This forces clients to *think about* what
they should do if such an exception were to be thrown.
So when I change my code and make it possible for a new
exception to be thrown, I would make it a checked exception
to once again put it into client programmer's faces. They will
have to recompile their classes and figure out how they want
to deal with this new possibility. If I felt it wasn't
important that they actually considered what their code should
do if my code threw this new exception, I'd make it an
On the other hand, people tend get upset when you deliver a new
version of a package (whether the package is your company's
product or just used in-house by other groups) that breaks
existing code that uses the package. In general, one should
strive to make updates binary compatible with previous
releases. If you want to get rid of something, for example,
don't just get rid of it, deprecate it and explain the
alternative in a doc comment.
But I think checked exceptions might be the exception to
this rule of avoiding breaking the client code. The checked
exceptions my package throws tells clients what errors I,
as designer of the package, felt were important or common
enough that client programmers, if they want their code
to be robust, would need to consciously decide how to
> Another approach is to use an instance variable in the exception
> class to indicate a subtype. This approach is useful for
> exceptions thrown by CORBA services, since CORBA IDL does not
> support an inheritance hierarchy for exceptions.
Yes, this makes sense in the CORBA IDL context. In general,
however, I would go with the "Define a different exception
type for each different kind of problem your code can
encounter," which lets people separate out code in different
catch clauses and use inheritance to catch a whole family of
exceptions in one clause.