Multi-catch & catch order
Catching multiple types in one block, and why order matters for subclasses.
Catching related exceptions cleanly
Multi-catch (Java 7+) lets one catch block handle several unrelated exception types separated by |:
try {
process();
} catch (IOException | SQLException e) {
// e is effectively final here
log(e.getMessage());
}
Rules for multi-catch:
- The alternatives cannot be in a subclass relationship — catch (Exception | IOException e) is a compile error because IOException is already an Exception.
- The variable e is effectively final inside the block — you cannot reassign it.
Catch order matters when you have multiple catch blocks: the most specific (narrowest) exception type must come before the more general ones. The compiler enforces this for checked exceptions but it is equally important for unchecked ones:
try {
parse();
} catch (NumberFormatException e) { // more specific first
System.out.println("bad number");
} catch (IllegalArgumentException e) { // more general second
System.out.println("bad arg");
} catch (RuntimeException e) { // most general last
System.out.println("runtime error");
}
If you put RuntimeException first, the NumberFormatException and IllegalArgumentException blocks become unreachable — a compile error for checked exceptions, but only a warning (not an error) for unchecked ones. The exam tests whether you catch subtypes before supertypes.