Can you have multiple catch blocks for one try?
Java allows using multiple catch blocks for one try:
Junior Level
Yes, you can!
Java allows using multiple catch blocks for one try:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.FileNotFoundException;
public class FileProcessor {
public String readFile(String path) {
try {
return Files.readString(Paths.get(path));
} catch (FileNotFoundException e) {
// Specific case - file doesn't exist
return "default content";
} catch (IOException e) {
// More general - other IO errors
throw new ServiceException("Failed to read file: " + path, e);
}
}
}
Rule: from specific to general
catch blocks must go from specific to general:
// Correct
try { ... }
catch (FileNotFoundException e) { } // Specific
catch (IOException e) { } // More general
catch (Exception e) { } // Most general
// Incorrect - won't compile!
try { ... }
catch (Exception e) { } // Catches everything!
catch (FileNotFoundException e) { } // Never executes
WHY order matters: “first match wins” mechanism
The compiler checks the order of catch blocks at compile time. When you write multiple catches, the compiler builds a type hierarchy and checks that each subsequent catch is not a subtype of a previous one.
At the compiler level:
- Compiler analyzes each catch block top to bottom.
- For each catch it checks: “Is there already a catch above that is a supertype of the current one?”
- If yes - compilation error
"exception X has already been caught", because code in the lower catch block is unreachable (unreachable code, JLS 14.21). - If no - catch is added to the Exception Table.
At the JVM level (runtime):
- On
athrow, JVM scans the Exception Table top to bottom. - First match by type (or supertype) captures control.
- Remaining catch blocks are not checked - even if they would also match.
This is called “first match wins”. Therefore the order determines which handler gets control.
try { ... }
catch (FileNotFoundException e) { ... } // #1: checked first
catch (IOException e) { ... } // #2: checked only if #1 didn't match
If FileNotFoundException is thrown in try, JVM finds a match in #1 and doesn’t reach #2, even though FileNotFoundException is also an IOException.
finally after all catches
try {
// code
} catch (IOException e) {
// IO handler
} catch (Exception e) {
// handler for the rest
} finally {
// Executes after any catch
}
When NOT to use multiple catch blocks
- Same handling - if all catch blocks do the same thing, use multi-catch (
A | B) - it’s shorter and more readable (Java 7+) - More than 5 catch blocks - sign of SRP violation, method does too much. Consider splitting into several methods
- Catch
Exceptionwhen specifics don’t matter - for generic logging, one catch is enough - In functional style - instead of catch use
Either/Trymonads (Vavr library) - When @ControllerAdvice is enough - in Spring REST one global handler replaces 10 catch blocks
Caveat: Java 7+ multi-catch as alternative
Starting from Java 7, instead of several separate catch blocks with identical logic, you can use multi-catch:
// Instead of:
catch (IOException e) {
log.error("Error", e);
throw new ServiceException(e);
}
catch (SQLException e) {
log.error("Error", e);
throw new ServiceException(e);
}
// Write:
catch (IOException | SQLException e) {
log.error("Error", e);
throw new ServiceException(e);
}
Multi-catch is preferable when handling is identical. Separate catches are only needed when logic differs (e.g., retry for IO, but not for SQL).
Middle Level
How JVM searches for handler
In the .class file, an Exception Table is created:
| from | to | target | type |
|---|---|---|---|
| 0 | 10 | 13 | FileNotFoundException |
| 0 | 10 | 25 | IOException |
| 0 | 10 | 37 | Exception |
When athrow occurs, JVM scans the table top to bottom until the first match.
Anti-pattern: code duplication
// Bad - duplication
try { ... }
catch (IOException e) {
log.error("Error", e);
throw new ServiceException(e);
}
catch (SQLException e) {
log.error("Error", e); // Same!
throw new ServiceException(e); // Same!
}
// Good - multi-catch
try { ... }
catch (IOException | SQLException e) {
log.error("Error", e);
throw new ServiceException(e);
}
Logic separation
If different handling is needed - separate catch blocks are justified:
try {
// code
} catch (FileNotFoundException e) {
log.warn("File not found, using default");
return getDefaultData();
} catch (IOException e) {
log.error("IO error", e);
throw new ServiceException(e);
}
Cost of Catch
The attempt to enter a catch itself is “free” until an exception is thrown. Having an Exception Table does not slow down execution of the try block.
Senior Level
Exception Table Size
Huge number of catch blocks can bloat method size beyond 64KB -> compilation error. This is a sure sign of SRP violation - method does too much.
Polymorphism vs Catch
Instead of 10 catch blocks, sometimes better:
// Alternative - handling through hierarchy
catch (BusinessException e) {
// Handles all subtypes: OrderException, PaymentException, etc.
handleBusinessError(e);
}
Or Pattern Matching (Java 17+):
catch (Exception e) {
if (e instanceof FileNotFoundException fnf) {
// fnf is already cast to type
} else if (e instanceof IOException io) {
// io is already cast to type
}
}
Catching Error
You can catch Error or Throwable, but after OutOfMemoryError the application state is unpredictable. Catch only for “last breath” - logging before crash.
Diagnostics
javap -v MyClass.class- shows the real Exception Table- Log Correlation - save common metadata (Trace ID) for all error types
- Static Analysis - Sonar warns about duplication in catch blocks
- Metrics - count each exception type via Micrometer
Interview Cheat Sheet
Must know:
- Multiple
catchblocks for onetry- allowed and widely used - Rule: from specific to general -
FileNotFoundExceptionbeforeIOExceptionbeforeException - Compiler checks order at compile time - wrong order = error “already been caught”
- JVM searches handler “first match wins” - scans Exception Table top to bottom until first match
- Having Exception Table doesn’t slow down
tryblock execution - checking is “free” until exception - If handling is identical - use multi-catch (
IOException | SQLException) instead of duplication - More than 5 catch blocks - sign of SRP violation, method does too much
Frequent follow-up questions:
- Why can’t
Exceptiongo beforeIOException? -Exceptioncatches everything,IOExceptionbecomes unreachable code - How does JVM search for handler? - Scans Exception Table top to bottom, first match captures control
- When do you need separate catches instead of multi-catch? - When handling logic differs (retry for IO, not for SQL)
- Does number of catches affect performance? - O(n) search in Exception Table, place frequent ones first
Red flags (NOT to say):
- “I put
catch (Exception e)first for simplicity” - won’t compile with more specific catches - “Many catch blocks don’t affect
tryperformance” - true, but affect search on exception - “I use catch for
Errorin business logic” - afterOutOfMemoryErrorstate is unpredictable - “I duplicate code in each catch” - use multi-catch when handling is identical
Related topics:
- [[25. What is multi-catch (catching multiple exceptions)]] - alternative when handling is identical
- [[26. In what order should catch blocks be arranged]] - detailed ordering explanation
- [[27. Can you rethrow an exception]] - rethrow from catch block
- [[1. What is the difference between checked and unchecked exceptions]] - which exceptions to catch
- [[4. Which exceptions must be handled]] - mandatory catches