Exception
matching
When
an exception is thrown, the exception-handling system looks through the
“nearest” handlers in the order they are written. When it finds a
match, the exception is considered handled, and no further searching occurs.
Matching
an exception doesn’t require a perfect match between the exception and
its handler. A derived-class object will match a handler for the base class, as
shown in this
example:
//: Human.java
// Catching Exception Hierarchies
class Annoyance extends Exception {}
class Sneeze extends Annoyance {}
public class Human {
public static void main(String[] args) {
try {
throw new Sneeze();
} catch(Sneeze s) {
System.out.println("Caught Sneeze");
} catch(Annoyance a) {
System.out.println("Caught Annoyance");
}
}
} ///:~
The
Sneeze
exception will be caught by the first
catch
clause that it matches, which is the first one, of course. However, if you
remove the first catch clause:
try {
throw new Sneeze();
} catch(Annoyance a) {
System.out.println("Caught Annoyance");
}
The
remaining catch clause will still work because it’s catching the base
class of
Sneeze.
Put another way,
catch(Annoyance
e)
will catch a
Annoyance
or
any class derived from it
.
This is useful because if you decide to add more exceptions to a method, if
they’re all inherited from the same base class then the client
programmer’s code will not need changing, assuming they catch the base
class, at the very least.
If
you try to “mask” the derived-class exceptions by putting the
base-class catch clause first, like this:
try {
throw new Sneeze();
} catch(Annoyance a) {
System.out.println("Caught Annoyance");
} catch(Sneeze s) {
System.out.println("Caught Sneeze");
}
the
compiler will give you an error message, since it sees that the
Sneeze
catch-clause can never be reached.
Exception
guidelines
- Fix
the problem and call the method (which caused the exception) again.
- Patch
things up and continue without retrying the method.
- Calculate
some alternative result instead of what the method was supposed to produce.
- Do
whatever you can in the current context and rethrow the
same
exception to a higher context.
- Do
whatever you can in the current context and throw a
different
exception to a higher context.
- Terminate
the program.
- Simplify.
If your exception scheme makes things more complicated, then it is painful and
annoying to use.
- Make
your library and program safer. This is a short-term investment (for debugging)
and a long-term investment (for application robustness).