Java try-catch-finally and multi-catch blocks
try block, catch block, finally block, multi-catch, exception variable, exception message, stack trace, re-throwing, try-with-resources preview
try-catch-finally
The try-catch-finally construct separates normal code from error-handling code and guarantees cleanup runs regardless of what happens inside.
Basic Structure
public int parseAndDivide(String numStr, int divisor) {
try {
int value = Integer.parseInt(numStr); // NumberFormatException possible
return value / divisor; // ArithmeticException possible
} catch (NumberFormatException e) {
System.err.println("Not a number: " + e.getMessage());
return 0;
} catch (ArithmeticException e) {
System.err.println("Division by zero");
return 0;
} finally {
System.out.println("parseAndDivide completed"); // always runs
}
}
Multi-Catch (Java 7+)
try {
riskyOperation();
} catch (IOException | SQLException e) {
logger.error("Data error", e);
throw new RuntimeException("Data access failed", e);
}
Multi-catch groups unrelated exceptions that share the same handler. The variable e is effectively final in a multi-catch block — you cannot reassign it.
finally runs even when a return statement executes inside try or catch. The only exception: System.exit() terminates the JVM immediately, bypassing finally.
Re-throwing wraps the original exception as the cause. Wrap checked exceptions in RuntimeException when you want to convert checked to unchecked — common in framework and stream-lambda code where checked exceptions are impractical to propagate.
Catch the most specific exception type first. If you put a broad catch before a narrow one, the narrow catch is unreachable — the compiler rejects it. Order catch blocks from most specific to most general when handling a hierarchy of exceptions.
