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:
//: c09:Human.java
// Catching exception hierarchies.
import com.bruceeckel.simpletest.*;
class Annoyance extends Exception {}
class Sneeze extends Annoyance {}
public class Human {
private static Test monitor = new Test();
public static void main(String[] args) {
try {
throw new Sneeze();
} catch(Sneeze s) {
System.err.println("Caught Sneeze");
} catch(Annoyance a) {
System.err.println("Caught Annoyance");
}
monitor.expect(new String[] {
"Caught Sneeze"
});
}
} ///:~
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, leaving only:
try {
throw new Sneeze();
} catch(Annoyance a) {
System.err.println("Caught Annoyance");
}
the code will still work because it’s catching the base class of Sneeze. Put another way, catch(Annoyance e) will catch an Annoyance or any class derived from it. This is useful because if you decide to add more derived exceptions to a method, then the client programmer’s code will not need changing as long as the client catches the base class exceptions.
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.err.println("Caught Annoyance");
} catch(Sneeze s) {
System.err.println("Caught Sneeze");
}
the compiler will give you an error message, since it sees that the Sneeze catch-clause can never be reached.