Exceptions and try-with-resources

Checked versus unchecked exceptions, how to catch and rethrow well, and closing resources without leaks.

The hierarchy

Everything descends from Throwable. Error signals JVM-level problems you should not catch. Exception splits into checked (must be handled or declared) and unchecked (RuntimeException and its children).

KindExamplesCompiler forces handling?
CheckedIOException, SQLExceptionYes
UncheckedNullPointerException, IllegalArgumentExceptionNo
ErrorOutOfMemoryError, StackOverflowErrorNo — do not catch

Handling

try {
    int value = Integer.parseInt(text);
} catch (NumberFormatException e) {
    System.err.println("Not a number: " + text);
} finally {
    cleanup();          // always runs
}

// multi-catch for unrelated types
try { risky(); }
catch (IOException | SQLException e) { log(e); }
⚠️
Catching Exception broadly hides bugs. Catch the narrowest type you can actually handle, and never swallow silently — log or rethrow.

try-with-resources

Anything implementing AutoCloseable can be declared inside the try parentheses and is closed automatically, in reverse order, even if the body throws.

try (var reader = Files.newBufferedReader(path);
     var conn = dataSource.getConnection()) {
    String line;
    while ((line = reader.readLine()) != null) {
        process(line);
    }
} catch (IOException | SQLException e) {
    throw new UncheckedIOException(new IOException(e));
}
  • Wrap and rethrow when the caller cannot act on a checked exception — but preserve the cause.
  • Custom exceptions should extend RuntimeException for programming errors, and be checked only when the caller can genuinely recover.
  • Objects.requireNonNull(arg, "name") at method entry turns a vague NPE into a precise message.

FAQ

Should my API throw checked exceptions?
Default to unchecked for anything the caller cannot fix. Checked exceptions are best reserved for recoverable conditions like I/O retries.
Is printStackTrace enough?
No. Use a logging framework with levels, and include context — request id, user, inputs — so the log is actionable.

Java collections Classes, records and interfaces

Last refreshed 2026-09-17.