Exceptions

74. Try-with-Resources

try-with-resources automatically closes AutoCloseable resources in reverse declaration order, even if an exception is thrown; exceptions from close() are suppressed and accessible via getSuppressed().

Java 7+ (try-with-resources); Java 9+ (effectively-final variable); Java 21

Explanation

Any class implementing AutoCloseable (one method: void close() throws Exception) can be used in a try-with-resources. Resources are closed in reverse order of declaration when the try block exits, regardless of whether it exited normally or via exception.

Suppressed exceptions: if both the try block and a close() call throw, the close() exception is added to the primary exception as a suppressed exception (primary.getSuppressed()). Without try-with-resources, a manually written finally block would silently swallow the original exception.

Java 9+: you can use an effectively-final variable declared before the try block: var stream = openStream(); try (stream) { ... } โ€” no need to re-declare inside the parentheses.

Example

import java.io.*;

public class TryWithResources {
    // Custom AutoCloseable
    static class Resource implements AutoCloseable {
        final String name;
        Resource(String name) {
            this.name = name;
            System.out.println("Opened: " + name);
        }
        void use() { System.out.println("Using: " + name); }
        @Override
        public void close() { System.out.println("Closed: " + name); }
    }

    // Throws on close โ€” demonstrates suppressed exceptions
    static class BrokenResource implements AutoCloseable {
        @Override
        public void close() throws Exception {
            throw new Exception("Close failed");
        }
        void use() { throw new RuntimeException("Use failed"); }
    }

    public static void main(String[] args) {
        // Multiple resources โ€” closed in REVERSE order (B then A)
        try (Resource a = new Resource("A"); Resource b = new Resource("B")) {
            a.use();
            b.use();
        }
        System.out.println();

        // Exception + suppressed close exception
        try (BrokenResource r = new BrokenResource()) {
            r.use(); // throws RuntimeException("Use failed")
        } catch (Exception primary) {
            System.out.println("Primary: " + primary.getMessage()); // Use failed
            for (Throwable s : primary.getSuppressed()) {
                System.out.println("Suppressed: " + s.getMessage()); // Close failed
            }
        }

        // Java 9+: effectively-final var before try
        Resource r = new Resource("Outer");
        try (r) {
            r.use();
        }
        System.out.println();

        // Classic use: file reading
        try (BufferedReader br = new BufferedReader(new StringReader("line1\nline2"))) {
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println("Read: " + line);
            }
        } catch (IOException e) {
            System.out.println("IO error: " + e.getMessage());
        }
    }
}

Sources