Exceptions, Assertions & Logging
Catching, Rethrowing & try-with-resources
Catch what you can handle; wrap-and-rethrow across abstraction boundaries; and let try-with-resources close everything that is
AutoCloseable — it is shorter and more correct than any finally block you would write.- try-with-resources closes in reverse order, even on exceptions — always prefer it (EJ 9)
- Suppressed exceptions: a close-failure doesn't mask the real one (
getSuppressed) - Multi-catch:
catch (IOException | SQLException e) - Chain causes when translating:
throw new StorageException(e)(EJ 73) finallyremains for non-resource cleanup (locks, counters)
try (var in = new Scanner(Path.of("in.txt"), StandardCharsets.UTF_8);
var out = new PrintWriter("out.txt", StandardCharsets.UTF_8)) {
while (in.hasNext())
out.println(in.next().toUpperCase());
} // out closed first, then in — exception or notThe old finally idiom had two flaws this fixes: nested try/finally noise per resource, and the masking bug — an exception thrown by close() in finally silently discarded the original exception from the body. With try-with-resources the body's exception wins and close-failures attach as suppressed exceptions, visible in the stack trace and via getSuppressed().
public UserProfile loadProfile(String id) {
try {
return parse(db.fetchRow(id));
} catch (SQLException e) {
// translate low-level detail into the abstraction callers understand,
// preserving the full diagnostic chain:
throw new ProfileStoreException("profile " + id, e);
}
}