Metadata Card
- Difficulty: (Novice Village 3-star)
- Prerequisites: Ch5 (Methods & Stack), Ch7 (OOP)
- Core concepts: 7 (try/catch/finally, exception propagation, checked vs unchecked, custom exceptions, try-with-resources, exception chaining, best practices)
- Estimated time: 4-6 hrs
The Breakthrough · Tracing the Origins
Master Chen opens a digital bank in Variable Village. Your code handles deposits, withdrawals, transfers — until the first exception blows up your screen.
The old approach: if-else everything. But what if the input isn't a number? What if the file isn't found? What if the network goes down? Every assumption adds another layer of if-else — until business logic drowns in defense code.
Your task: The system needs to handle:
- Invalid amounts (negative numbers)
- Network failures during transfers (partial updates)
- Missing configuration files
- Null pointers everywhere
try/catch/finally
try {
processTransaction();
} catch (RuntimeException e) {
System.out.println("Transaction failed: " + e.getMessage());
} finally {
// Always executes — for cleanup
closeResources();
}try = danger zone. catch = safety net. finally = cleanup (always runs, even on return).
Checked vs Unchecked Exceptions
| Type | Checked when | Example |
|---|---|---|
| Checked | Compile time | IOException, SQLException |
| Unchecked | Runtime | NullPointerException, ArithmeticException |
Checked = "caller, you must deal with this risk."
void loadConfig() throws FileNotFoundException { ... }
// Caller must try/catch or declare throwsCustom Exceptions
public class BankException extends RuntimeException {
public BankException(String message) { super(message); }
public BankException(String message, Throwable cause) { super(message, cause); }
}
public class InsufficientBalanceException extends BankException {
public InsufficientBalanceException(int balance, int amount) {
super("Insufficient balance: current " + balance + ", required " + amount);
}
}try-with-resources (Java 7+)
// Old way: 18 lines of cleanup
// New way:
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} // Auto-closes br!Only classes implementing AutoCloseable can be used.
Exception Chaining
// DON'T — bury the original exception
try { db.update(account); }
catch (SQLException e) { throw new RuntimeException("Update failed"); }
// DO — wrap with original cause
try { db.update(account); }
catch (SQLException e) { throw new RuntimeException("Update failed", e); }Final Challenge: Write a Calculator that throws meaningful exceptions. Build a BankSystem with TransferException that carries from, to, amount, reason. Use try-with-resources to write failed transactions to a log file.
Traveler's Notes
The essence of exception handling isn't "catching" — it's "letting go of what you can, catching what you must."
Checked exceptions are Java's unique design — making ignored risks visible.
try-with-resources over finally for resource cleanup.
Never eat the original exception — chain it.