How to learn Exception Handling
An exception reports that a method could not complete its contract normally. Catch an exception only where the program can add context, recover, translate it to a more suitable abstraction, or perform boundary-level reporting. Catching and ignoring it makes the program harder to diagnose.
Checked exceptions must be caught or declared; unchecked exceptions do not have that compiler requirement. That distinction does not decide whether an error is important. It describes how the API communicates the failure to callers.
Recommended learning order
- Read the failure: Inspect the exception type, message, cause, and first relevant stack frame before changing code.
- Catch narrowly: Wrap only the statements expected to fail and catch the most specific type you can handle.
- Preserve resources and causes: Use try-with-resources for AutoCloseable values and retain the original exception when translating failures.
- Design exception contracts: Validate method inputs, document expected failures, and create a custom exception only when it adds a meaningful domain distinction.
Tested example: Translate a parsing failure with its cause
The boundary method gives callers a useful domain message while retaining NumberFormatException as the cause for debugging. It does not catch unrelated failures.
public class Main {
static int positiveCount(String text) {
try {
int value = Integer.parseInt(text);
if (value < 0) throw new IllegalArgumentException("count must not be negative");
return value;
} catch (NumberFormatException cause) {
throw new IllegalArgumentException("count must be an integer", cause);
}
}
public static void main(String[] args) {
try {
positiveCount("four");
} catch (IllegalArgumentException error) {
System.out.println(error.getMessage());
System.out.println(error.getCause().getClass().getSimpleName());
}
}
}Expected output
count must be an integer
NumberFormatExceptionCommon mistakes
- Catching Exception around a large block, which hides which operation was expected to fail.
- Logging an exception and rethrowing it at every layer, producing duplicate noise without new context.
- Returning from finally or throwing a new failure there, which can suppress the original result or exception.
- Using exceptions as ordinary loop or branch control when a direct condition would express the expected case.
How to practice
Start with one catch, then multiple specific catches, finally, try-with-resources, and custom exceptions. In each answer, identify who can recover and whether the original cause remains available.
Exercises to do first
- Basic try-catch — Handle one expected failure at the smallest useful boundary.
- Try with resources — Let Java close an AutoCloseable resource on success or failure.
- Custom exception — Create a domain-specific failure only where it clarifies the caller contract.