iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

try-with-resources

try-with-resources guarantees that anything implementing AutoCloseable is closed when the block exits — by normal completion or by exception. It replaces the verbose try/finally pattern and removes the entire class of "I forgot to close the stream" bugs.

try-with-resources patterns and gotchas

EXAMPLE
import java.io.*;
import java.nio.file.*;
import java.sql.*;
import java.util.zip.*;

public class TryWithResources {

    // 1) Single resource
    public static String read(Path p) throws IOException {
        try (var reader = Files.newBufferedReader(p)) {
            return reader.readLine();
        }   // reader.close() is called automatically
    }

    // 2) Multiple resources — semicolon-separated, closed in REVERSE order
    public static void copy(Path src, Path dst) throws IOException {
        try (var in  = Files.newInputStream(src);
             var out = Files.newOutputStream(dst)) {
            in.transferTo(out);
        }   // out.close() THEN in.close()
    }

    // 3) Database — Connection, Statement, ResultSet all AutoCloseable
    public static int countOrders(String url, String user, String pw) throws SQLException {
        try (var conn = DriverManager.getConnection(url, user, pw);
             var stmt = conn.prepareStatement("SELECT COUNT(*) FROM orders");
             var rs   = stmt.executeQuery()) {
            return rs.next() ? rs.getInt(1) : 0;
        }
    }

    // 4) Streams (Stream<T>) implement AutoCloseable — close to release file handles
    public static long countLines(Path p) throws IOException {
        try (var stream = Files.lines(p)) {
            return stream.count();
        }
    }

    // 5) Suppressed exceptions — if both the body AND close() throw,
    //    the BODY exception is primary; the close exception is added as suppressed.
    public static void demo() throws IOException {
        try (var noisy = new NoisyClose()) {
            throw new IOException("primary");
        }
        // catch -> ex.getSuppressed() returns [NoisyClose.close exception]
    }

    static class NoisyClose implements AutoCloseable {
        @Override public void close() throws IOException {
            throw new IOException("close failed");
        }
    }

    // 6) Reusing an EXISTING variable (Java 9+) — no re-declaration
    public static void reuse(BufferedReader existing) throws IOException {
        try (existing) {
            existing.readLine();
        }
    }

    // 7) Wrapping streams stays simple
    public static void writeGzipped(Path p, String text) throws IOException {
        try (var out = new GZIPOutputStream(Files.newOutputStream(p));
             var w   = new OutputStreamWriter(out)) {
            w.write(text);
        }
    }

    // 8) Common pitfalls
    // - Trying to use a resource AFTER the try block (it has been closed)
    // - Implementing AutoCloseable without making close() idempotent
    // - Catching exception INSIDE the try and continuing to use the resource
    //   that may already be in a bad state
    // - Forgetting that Streams from Files.lines / Files.list need closing

    // 9) Custom AutoCloseable
    public static class Tx implements AutoCloseable {
        private final Connection conn;
        private boolean committed;
        public Tx(Connection conn) throws SQLException { this.conn = conn; conn.setAutoCommit(false); }
        public void commit() throws SQLException { conn.commit(); committed = true; }
        @Override public void close() throws SQLException {
            if (!committed) conn.rollback();
            conn.setAutoCommit(true);
        }
    }

    // Usage:
    // try (var tx = new Tx(conn)) {
    //   doWork(conn);
    //   tx.commit();
    // }   // rollback() runs if commit() was not called
}

Why it matters

Move every IO / DB call to try-with-resources from the moment you start a Java codebase. The pattern is shorter than try/finally, never leaks handles on exceptions, and the suppressed-exception story makes "primary failure + cleanup failure" the readable single stack trace it should be.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
try (var in = new BufferedReader(new FileReader("input.txt"))) {
    return in.lines().count();
}
Try it Yourself »

Discussion

Loading…