Last 30 Days
No notifications
An exception is Java's way of saying "something went wrong, here's a typed object describing what." You handle it with try/catch, clean up with finally (or better, try-with-resources), and propagate with throws. Java is famous (and infamous) for splitting exceptions into *checked* (must be handled) and *unchecked* (RuntimeException family).
# Exceptions
Throwable
├── Error ← JVM-level (OutOfMemoryError) — don't catch
└── Exception
├── RuntimeException ← UNCHECKED (NullPointerException, IllegalArgumentException, …)
└── (everything else) ← CHECKED (IOException, SQLException, …)catch it or declare it with throws.try {
risky();
} catch (FileNotFoundException e) {
System.err.println("missing: " + e.getMessage());
} catch (IOException e) {
System.err.println("io: " + e.getMessage());
} finally {
System.out.println("always runs");
}
Order matters — more specific exceptions go first.try { … }
catch (IOException | SQLException e) { // pipe-separated
log(e);
}AutoCloseable is auto-closed in reverse order, even if an exception is thrown.
try (var br = new BufferedReader(new FileReader("data.txt"))) {
return br.readLine();
} // br.close() called automaticallythrow new X() — *raise* an exception now.throws X (in method signature) — *declare* this method may raise X.public static int parse(String s) throws NumberFormatException {
if (s == null) throw new IllegalArgumentException("s is null");
return Integer.parseInt(s);
}public class InsufficientFundsException extends RuntimeException {
private final double shortfall;
public InsufficientFundsException(double shortfall) {
super("short by $" + shortfall);
this.shortfall = shortfall;
}
public double getShortfall() { return shortfall; }
}
Extend RuntimeException for unchecked, plain Exception for checked.try { db.query(); }
catch (SQLException e) {
throw new ServiceException("user lookup failed", e); // wrap, keep cause
}
Use e.getCause() later to recover the original.