Try-With-Resources in Java

Naveen AnamaneniUpdated · 5 min read

Files, database connections and network sockets are resources: borrowed from the operating system, and they must be given back by calling close(). Forget, and the program slowly runs out of file handles or connections. Writing close() in a finally block works but is long and easy to get wrong. Try-with-resources (Java 7) lets you open resources in the try header, and Java closes them automatically at the end, however the block ends.

Opening and Closing Automatically

Open A then B; close B then A, even when the body fails
Resources.java▶ Try it
public class Resources {
    static class Connection implements AutoCloseable {
        private final String name;
 
        Connection(String name) {
            this.name = name;
            System.out.println("open " + name);
        }
 
        void send(String message) {
            if (message.isBlank()) {
                throw new IllegalArgumentException("empty message");
            }
            System.out.println(name + " sent: " + message);
        }
 
        @Override
        public void close() {
            System.out.println("close " + name);
        }
    }
 
    public static void main(String[] args) {
        try (Connection db = new Connection("database");
             Connection sms = new Connection("sms-gateway")) {
            db.send("order saved for Navika");
            sms.send(" ");
        } catch (IllegalArgumentException e) {
            System.out.println("caught: " + e.getMessage());
        }
    }
}
Output
open database
open sms-gateway
database sent: order saved for Navika
close sms-gateway
close database
caught: empty message

How it works

  1. Resources are declared in parentheses after try, separated by semicolons. Each must implement AutoCloseable.
  2. The body throws an exception on the second send.
  3. Before the catch runs, Java closes both resources, in reverse order of opening: the last one opened is closed first, so a resource is never closed while something opened after it still depends on it.
  4. Only then does the catch run.

Why It Beats finally

The same job with finally needs a null check, a nested try for close(), and still loses information when closing fails:

The old way
Connection db = null;
try {
    db = new Connection("database");
    db.send("order saved");
} finally {
    if (db != null) {
        db.close();          // if this throws, the original exception is lost
    }
}
finallytry-with-resources
Lines of codeMany, with null checksOne header
Forgetting to closePossibleImpossible
Several resourcesNested try blocksListed in one header, closed in reverse order
Exception while closingReplaces the original exceptionKept as a suppressed exception; the original survives (see "Suppressed Exceptions in Java")

Real Resources

Most JDK classes that hold something open implement AutoCloseable, so they work in the header directly: FileReader, BufferedReader, Scanner reading a file, InputStream and OutputStream, JDBC Connection, Statement and ResultSet, and ExecutorService (since Java 19). File and database lessons later in the course use try-with-resources everywhere.

Common Mistakes

Creating the resource before the try and forgetting to put it in the header. Then it isn't closed automatically.

Wrapping a Scanner on System.in in try-with-resources. Closing it closes System.in for the rest of the program.

Expecting resources to still be usable in the catch or finally. They're already closed, and they're out of scope.

Interview Corner

What is try-with-resources?

It's a form of the try statement, introduced in Java 7, that declares one or more resources in parentheses after try. Each resource must implement AutoCloseable, and Java automatically calls close() on all of them when the block finishes, normally or because of an exception, in the reverse order of declaration. Exceptions thrown while closing are added as suppressed exceptions to the main one.

In what order are resources closed?

In the reverse order of their declaration: the last resource opened is the first one closed. This ensures resources that depend on earlier ones are released first.

Practice

  1. Easy: Give the Connection class a third instance, "email", in the header, and predict the order of the "open" and "close" lines.
  2. Harder: Write a Timer class that implements AutoCloseable, records the time in its constructor and prints the elapsed milliseconds in close(). Use it to time a loop.

Quick check: try-with-resources

4 questions
1What interface must a resource implement?
2Resources A and B are opened in that order. In what order are they closed?
3When does closing happen relative to catch?
4What happens to an exception thrown by close()?

Key Takeaways

Was this tutorial helpful?

Lesson 223 of 482