Exception Handling
Checked vs unchecked, try/catch/finally, try-with-resources, and custom exceptions.
On this page
Things go wrong: files vanish, networks drop, users type nonsense. Exceptions are Java's structured way to signal and handle these problems without your whole program crashing. Handled well, they make software robust; handled poorly, they hide bugs.
What is an exception?
An exception is an object that represents something going wrong. When a problem occurs, Java throws an exception; if nothing catches it, the program stops and prints a stack trace.
A smoke alarm doesn't put out the fire - it signals a problem loudly so someone can respond. An exception is that alarm: it interrupts normal flow and hands control to code that knows how to deal with the situation. Ignore the alarm, and the building (program) evacuates (crashes).
try / catch / finally
Wrap risky code in a try block; handle failures in catch; run cleanup
in finally (which always runs, success or failure):
try {
int result = 10 / divisor; // might throw ArithmeticException
System.out.println(result);
} catch (ArithmeticException e) {
System.out.println("Can't divide by zero!");
} finally {
System.out.println("This always runs.");
}You can catch multiple types, most specific first:
try {
riskyOperation();
} catch (FileNotFoundException e) {
// handle a missing file specifically
} catch (IOException e) {
// handle any other I/O problem
}Checked vs. unchecked exceptions
Java has two families, and the difference matters:
| Checked | Unchecked (Runtime) | |
|---|---|---|
| Examples | IOException, SQLException | NullPointerException, IllegalArgumentException |
| When | Expected, recoverable problems | Programming bugs |
| Compiler | Forces you to handle or declare | Optional |
A checked exception is a forecast of rain: the compiler insists you prepare for it (handle or declare it). An unchecked exception is tripping over your own shoelaces - a bug you should just fix, so the compiler doesn't nag. Checked means "this can reasonably fail even in correct code."
A method declares checked exceptions it might throw with throws:
void readConfig() throws IOException {
Files.readString(Path.of("config.txt")); // may throw IOException
}try-with-resources: automatic cleanup
Resources like files and database connections must be closed. try-with- resources closes them automatically, even if an exception occurs:
try (var reader = Files.newBufferedReader(Path.of("data.txt"))) {
System.out.println(reader.readLine());
} // reader is closed automatically here - no finally neededAlways prefer try-with-resources
Manually closing resources in finally is verbose and easy to get wrong (what if
close() also throws?). Any resource implementing AutoCloseable works with
try-with-resources - use it for files, streams, sockets, and connections.
Custom exceptions
Create your own exception types for your domain by extending Exception
(checked) or RuntimeException (unchecked):
class InsufficientFundsException extends RuntimeException {
InsufficientFundsException(String message) {
super(message);
}
}
void withdraw(double amount) {
if (amount > balance) {
throw new InsufficientFundsException("Balance too low");
}
balance -= amount;
}Best practices
- Catch specific exceptions, not a blanket
catch (Exception e). - Never swallow silently - an empty catch block hides bugs. At minimum, log.
- Don't use exceptions for normal flow - they're for exceptional situations.
- Include context in messages: what failed and why.
- Fail fast - validate inputs early with
IllegalArgumentException.
The worst catch block
An empty catch (Exception e) {} is a bug-hiding trap: it silences problems so
they resurface later as baffling behavior. If you truly can't handle it, let it
propagate - don't bury it.
Quick check
What is the key difference between checked and unchecked exceptions?
Key takeaways
- An exception is an object signaling a problem; unhandled, it stops the program.
- Use try to wrap risky code, catch to handle failures, and finally for cleanup that always runs.
- Checked exceptions (compiler-enforced) model recoverable problems; unchecked model bugs.
- try-with-resources auto-closes AutoCloseable resources - prefer it over manual finally.
- Create custom exceptions for your domain; catch specifically, never swallow silently, and fail fast.
Next, we'll master the Collections Framework - the resizable lists, sets, and maps you'll reach for in nearly every program.