Order the catch clauses so a missing file and a general I/O failure are both handled
readConfig opens a settings file and must react differently to two failures: a missing file (FileNotFoundException) falls back to the defaults, while any other I/O failure (IOException) returns null.
Constraints:
- both
catchclauses must be present and the class must compile - do not merge them into one clause and do not catch
Exception Config.parsemay itself throwIOException
Config readConfig(String path) {
try (var in = new FileInputStream(path)) {
return Config.parse(in);
}
// your code here
}
Write the implementation.
Java scans the catch clauses top-down and enters the first one whose type is assignable from the thrown exception, so the subclass has to come first: catch (FileNotFoundException e) and only then catch (IOException e). In the opposite order the broad clause already handles the subclass, the narrow one becomes unreachable, and the compiler rejects it outright.
- ✗Putting
catch (Exception e)first and a narrower clause below it - ✗Believing
catchclauses are matched by best fit, like overload resolution - ✗Thinking an unreachable
catchis a warning rather than a compile error
- →What changes if the two exception types are unrelated instead of subclass and superclass?
- →How does a multi-catch clause interact with these ordering rules?
Solution
Config readConfig(String path) {
try (var in = new FileInputStream(path)) {
return Config.parse(in);
} catch (FileNotFoundException e) {
return Config.defaults();
} catch (IOException e) {
return null;
}
}
Why only this order works. FileNotFoundException is a subclass of IOException. The catch clauses are tested top-down, and the first one whose type is assignable from the thrown object runs. Put IOException first and it catches FileNotFoundException too — control never reaches the second clause.
That is not merely dead code, it is a compile error:
error: exception FileNotFoundException has already been caught
} catch (FileNotFoundException e) {
^
If the types are unrelated (IOException and SQLException), order does not matter — neither absorbs the other, and the compiler accepts either arrangement. The "most specific first" rule only bites along a single branch of the hierarchy.
The practical consequence: a catch (Exception e) anywhere in the middle of the list kills every clause below it, so a broad catch — if you need one at all — belongs last.