IOException in Java
Problem
FileNotFoundException is a subtype of IOException, so a catch block written for the broader IOException still catches a missing-file failure — it just doesn't distinguish it from any other kind of I/O error.
Attempt an I/O operation that can fail in more than one way, and handle any failure through a single general catch.
Java Program
import java.io.FileReader;
import java.io.IOException;
public class IOExceptionExample {
public static void main(String[] args) {
try {
FileReader reader = new FileReader("missing-file.txt");
} catch (IOException e) {
// getSimpleName() shows the specific subtype the general catch still caught
System.out.println("Error: Could not open file - " + e.getClass().getSimpleName());
}
}
}Output
Core Logic
Catching IOException instead of FileNotFoundException specifically still handles the same missing-file failure, because FileNotFoundException is-a IOException — the catch just can't tell which specific subtype occurred without asking.
- 1
new FileReader("missing-file.txt")throws aFileNotFoundExceptionwhen the file doesn't exist, exactly as before. - 2
catch (IOException e)matches it anyway, sinceFileNotFoundException extends IOException. - 3
e.getClass().getSimpleName()reveals the exception's actual runtime type, even though the catch clause only named its supertype. - 4A single
IOExceptioncatch would just as readily catch a different I/O failure — a read error, a permissions problem — without needing a separate catch block for each one.
IOException clause, and the printed class name still shows FileNotFoundException underneath.Key Point: Reach for the specific subtype (FileNotFoundException) when the response genuinely differs by failure type; reach for the supertype (IOException) when one recovery path is good enough for any I/O failure that could occur — this file and FileNotFoundException.mdx demonstrate exactly that choice on the identical scenario.