EMZETT.
Login

try-with-resources

In short: A try variant that automatically closes a resource (e.g. a file or database connection) as soon as the block is left — regardless of whether normally or via an exception.

In more detail: The resource is declared directly in the parentheses after try and has to implement the interface AutoCloseable. Before Java 7, closing had to happen manually in a finally block — easy to forget and error-prone, especially with several resources at once.

try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"))) {
    System.out.println(reader.readLine());
}

In Depth

// Before Java 7: manual closing in finally, easy to forget
BufferedReader reader = null;
try {
    reader = new BufferedReader(new FileReader("file.txt"));
    System.out.println(reader.readLine());
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if (reader != null) {
        try { reader.close(); } catch (IOException e) { /* this can blow up too */ }
    }
}
 
// With try-with-resources: compact, automatically closed, even on an exception
try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"))) {
    System.out.println(reader.readLine());
} catch (IOException e) {
    e.printStackTrace();
}
 
// Several resources at once, separated by semicolons:
try (var in = new FileReader("source.txt"); var out = new FileWriter("target.txt")) {
    // both are guaranteed to be closed, in reverse declaration order
}

The old pattern (in the first example above) shows why try-with-resources was introduced: the manual finally block itself needs another nested try/catch, because close() can also throw an IOException — with several resources, this quickly becomes confusing and error-prone, and it’s easy to simply forget the closing in one of the many possible code paths. try-with-resources handles this completely: every resource declared in the parentheses is guaranteed to be closed as soon as the block is left, whether normally, via a return, or via an exception — and in reverse order of declaration (the resource opened last is closed first, analogous to a stack).

Making your own classes AutoCloseable

The prerequisite is that the resource implements the AutoCloseable interface (or its stricter sub-interface Closeable, which explicitly restricts close() to IOException), which prescribes exactly one method: close(). All standard I/O classes like BufferedReader, FileWriter, Scanner, or database connections (java.sql.Connection) already satisfy this — but you can also have your own classes implement AutoCloseable, to make them usable in try-with-resources:

class Timer implements AutoCloseable {
    private final long start = System.nanoTime();
    private final String name;
 
    Timer(String name) { this.name = name; }
 
    @Override
    public void close() {
        long durationMs = (System.nanoTime() - start) / 1_000_000;
        System.out.println(name + " took " + durationMs + " ms");
    }
}
 
try (Timer t = new Timer("Calculation")) {
    // any code whose runtime you want to measure
}
// automatically prints the elapsed time when the block is left

This pattern is often used for resources that actually have nothing to do with files — e.g. timing, locking/unlocking a lock, or opening/closing a transaction.

Suppressed exceptions

A subtle but important aspect: what happens if BOTH the code in the try block throws an exception AND close() itself throws an exception? With try-with-resources, the exception from the try block is propagated as the “primary” one, while the exception from close() is attached to it as “suppressed” — retrievable via getSuppressed() on the primary exception. With the old, manual finally pattern, by contrast, the original exception was often lost entirely, because an exception thrown in the finally block overwrites the one from the try block — a genuine, often overlooked bug in older code.

Distinction from normal try/catch/finally

try-with-resources doesn’t replace catch/finally in general, it specifically supplements resource management: catch blocks for the actual error handling can still be attached directly (as in the example above), and an additional finally block is also still allowed, for cleanup work that is NOT resource-specific. The decisive difference from exceptions in general: try-with-resources doesn’t handle errors, it only guarantees that resources are released under all circumstances.

See also: Exceptions, BufferedReader, Files, Interface