00:00

try-with-resources in Java – Explained with Examples

Last updated: 7 min read

Files, network sockets, database connections and streams hold operating-system resources that must be closed when you are done, even if something goes wrong. try-with-resources, introduced in Java 7, closes such resources automatically at the end of a try block. It replaces long, error-prone try-finally code with a single clear statement.

This tutorial shows how to use try-with-resources, how several resources are closed, what happens to exceptions thrown while closing, and how to make your own classes work with it.

1. Syntax

try-with-resources syntax
try (ResourceType resource = new ResourceType(...)) {
    // use the resource
}   // resource.close() is called automatically here

try (A a = ...; B b = ...) {   // several resources, separated by semicolons
    ...
} catch (SomeException e) {    // catch and finally are optional
    ...
}

Any object whose class implements java.lang.AutoCloseable (or its sub-interface java.io.Closeable) can be declared in the parentheses.

2. Reading a File Safely

ReadFileDemo.java
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

public class ReadFileDemo {
    public static void main(String[] args) throws IOException {
        Path file = Files.createTempFile("notes", ".txt");
        Files.writeString(file, "first line\nsecond line\nthird line\n");

        // The reader is closed automatically at the end of the try block
        try (BufferedReader reader = Files.newBufferedReader(file)) {
            String line;
            int n = 1;
            while ((line = reader.readLine()) != null) {
                System.out.println(n++ + ": " + line);
            }
        } catch (IOException e) {
            System.out.println("Could not read file: " + e.getMessage());
        }

        Files.delete(file);
    }
}
Output
1: first line
2: second line
3: third line

The reader is closed when the try block ends, whether the loop finishes normally or an exception is thrown. No finally block or null checks are needed.

3. Multiple Resources and Closing Order

Resources are opened in the order they are declared and closed in the reverse order, so a resource is always closed before the ones it might depend on:

CloseOrder.java
public class CloseOrder {
    static class Resource implements AutoCloseable {
        private final String name;
        Resource(String name) { this.name = name; System.out.println("open  " + name); }
        void use() { System.out.println("use   " + name); }
        @Override public void close() { System.out.println("close " + name); }
    }

    public static void main(String[] args) {
        try (Resource db = new Resource("database");
             Resource file = new Resource("file");
             Resource socket = new Resource("socket")) {
            db.use();
            file.use();
            socket.use();
        }
        System.out.println("all resources closed (in reverse order)");
    }
}
Output
open  database
open  file
open  socket
use   database
use   file
use   socket
close socket
close file
close database
all resources closed (in reverse order)

Implementing AutoCloseable is all it takes to make your own class work with try-with-resources.

4. Suppressed Exceptions

What if the try block throws an exception and then close() throws another one? With try-finally, the second exception would replace the first and the real cause would be lost. try-with-resources keeps the original exception and attaches the closing exception to it as a suppressed exception:

SuppressedExceptions.java
public class SuppressedExceptions {
    static class FlakyResource implements AutoCloseable {
        @Override public void close() {
            throw new IllegalStateException("error while closing");
        }
    }

    public static void main(String[] args) {
        try (FlakyResource r = new FlakyResource()) {
            throw new IllegalArgumentException("error while working");
        } catch (Exception e) {
            System.out.println("main exception: " + e.getMessage());
            for (Throwable s : e.getSuppressed()) {
                System.out.println("suppressed:     " + s.getMessage());
            }
        }
    }
}
Output
main exception: error while working
suppressed:     error while closing

Stack traces print suppressed exceptions too, so no information is lost.

5. Old Style vs try-with-resources

OldStyleVsNew.java
import java.io.StringReader;
import java.io.BufferedReader;
import java.io.IOException;

public class OldStyleVsNew {
    // Before Java 7: verbose and easy to get wrong
    static String firstLineOld(String text) throws IOException {
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new StringReader(text));
            return reader.readLine();
        } finally {
            if (reader != null) {
                reader.close();
            }
        }
    }

    // Java 7+: the same in a few lines
    static String firstLineNew(String text) throws IOException {
        try (BufferedReader reader = new BufferedReader(new StringReader(text))) {
            return reader.readLine();
        }
    }

    // Java 9+: an effectively final variable can be used directly
    static String firstLineJava9(BufferedReader reader) throws IOException {
        try (reader) {
            return reader.readLine();
        }
    }

    public static void main(String[] args) throws IOException {
        String text = "hello\nworld";
        System.out.println(firstLineOld(text));
        System.out.println(firstLineNew(text));
        System.out.println(firstLineJava9(new BufferedReader(new StringReader(text))));
    }
}
Output
hello
hello
hello
  • The old style needs a variable outside the try, a null check and a finally block, and it loses the original exception if close() fails.
  • Since Java 9, an existing effectively final variable can be listed directly: try (reader) { ... }.

6. AutoCloseable vs Closeable

AutoCloseableCloseable
Packagejava.langjava.io
SinceJava 7Java 5
close() throwsExceptionIOException
Calling close twiceMay have side effectsMust have no effect (idempotent)
Typical implementationsJDBC Connection, ExecutorService (Java 19+), your own classesStreams, readers, writers, channels

7. Common Resources to Use It With

  • File I/O: FileInputStream, BufferedReader, Files.lines() streams, Scanner on a file.
  • JDBC: Connection, PreparedStatement, ResultSet.
  • Networking: Socket, ServerSocket, HTTP response bodies.
  • Concurrency: ExecutorService (Java 19+), which waits for tasks when closed.
  • Locks and other custom resources, by wrapping them in an AutoCloseable.

8. Rules and Tips

  • Resources declared in the parentheses are implicitly final and are visible only inside the try block.
  • Resources are closed before any catch or finally block runs.
  • If a resource initialiser throws, resources already opened are still closed.
  • A resource that is null is simply skipped when closing.
  • Declare each resource separately; nesting constructors like new BufferedReader(new FileReader(f)) only registers the outer one (usually fine, because closing it closes the inner one).

9. Summary

  • try-with-resources automatically closes AutoCloseable resources at the end of the try block.
  • Multiple resources are closed in reverse order of declaration.
  • Exceptions from close() are attached to the main exception as suppressed exceptions.
  • It is shorter and safer than try-finally; Java 9 allows existing effectively final variables.
  • Implement AutoCloseable to make your own classes work with it.

Related Tutorials

Reference: Oracle Java Tutorials: The try-with-resources Statement