Custom exceptions & common built-ins
Writing your own exception types, chaining causes, and picking the right built-in.
Writing your own exception types
Custom exceptions let you communicate domain-specific errors in the type system. The choice of base class determines checkedness:
// Checked — callers MUST handle or declare
public class InsufficientFundsException extends Exception {
private final double amount;
public InsufficientFundsException(double amount) {
super("Insufficient funds: need " + amount + " more");
this.amount = amount;
}
// Constructor that chains a cause
public InsufficientFundsException(double amount, Throwable cause) {
super("Insufficient funds: need " + amount + " more", cause);
this.amount = amount;
}
public double getAmount() { return amount; }
}
// Unchecked — extend RuntimeException
public class ConfigurationException extends RuntimeException {
public ConfigurationException(String msg) { super(msg); }
public ConfigurationException(String msg, Throwable cause) { super(msg, cause); }
}
When to make an exception checked vs unchecked:
- Checked: the caller can reasonably recover — InsufficientFundsException makes sense to catch and prompt the user.
- Unchecked: the caller cannot reasonably recover, or the exception indicates a programming error — ConfigurationException at startup is usually fatal.
Modern Java (and most frameworks) lean toward unchecked exceptions for application logic; checked exceptions for I/O and transactional operations where retry/fallback is expected.
Common built-in exceptions to know for OCP:
| Exception | Unchecked? | Cause |
|---|---|---|
| NullPointerException | yes | null dereference |
| IllegalArgumentException | yes | invalid method argument |
| IllegalStateException | yes | object in wrong state |
| ClassCastException | yes | invalid downcast |
| NumberFormatException | yes | bad numeric string |
| StackOverflowError | yes (Error) | infinite recursion |
| ArithmeticException | yes | e.g. integer divide by zero |
| IOException | checked | I/O failure |
| FileNotFoundException | checked | file not found (extends IOException) |
Always provide at minimum two constructors: one taking a String message, and one taking both a String and a Throwable cause — so callers can wrap underlying exceptions without losing the chain.