Skip to content
Theory · Exceptions · lesson 10 of 12

try-with-resources

Some things a program opens must be closed: a file, a database connection, a network connection. A file left open keeps system resources busy, and what was written to it may never reach the disk. You can close such things in finally, but that code is long, and people often forget to write it.

Remember the door from the lesson on finally. Now picture a door with a closer, a spring that shuts it by itself. You walk through, and the door closes without your help. Java can open things the same way: in a special try that closes them by itself.

JAVA
public class Main {
    public static void main(String[] args) {
        try (Door door = new Door("A")) {
            System.out.println("inside " + door.name());
        }
        System.out.println("after");
    }
}

record Door(String name) implements AutoCloseable {
    @Override
    public void close() {
        System.out.println("close " + name);
    }
}

The program prints:

TEXT
inside A
close A
after

A resource and AutoCloseable

A resource is an object that has to be closed after use. Let's go through the program step by step:

  1. record Door(String name) implements AutoCloseable is our door resource. AutoCloseable is an interface from the standard library with one method, close(), and Door implements it.
  2. try (Door door = new Door("A")) declares the resource in parentheses right after try.
  3. The body of the block prints inside A.
  4. On the way out of the block, Java calls door.close() by itself, and close A is printed.
  5. Then the code after try runs and prints after.

try-with-resources is a try with resources in parentheses: when the block is left, it calls close() on each of them. The compiler turns such a try into try and finally with a call to close(), the very code you would otherwise write by hand.

Only an object of a class that implements AutoCloseable can be a resource. In the interface, the method close() is declared with throws Exception. Our Door throws nothing and does not write throws, so no catch is needed here.

Interviewers ask: what is try-with-resources, and what does a resource need? The answer: a block that closes its resources by itself whichever way it is left, and a resource must implement AutoCloseable.

Several resources

Resources in the parentheses are separated by semicolons:

JAVA
try (Door a = new Door("A"); Door b = new Door("B")) {
    System.out.println("inside " + a.name() + b.name());
}
TEXT
inside AB
close B
close A

Resources close in reverse order: the last one opened closes first. It is the same with doors: you walked in through A, then through B, and on the way out you pass B first. So a resource opened later may use one opened earlier: while it is closing, the earlier one still works.

An exception inside try

A resource is closed whichever way the block is left, an exception included:

JAVA
try (Door door = new Door("C")) {
    System.out.println("inside " + door.name());
    Integer.parseInt("x");
} catch (NumberFormatException e) {
    System.out.println("caught");
}
TEXT
inside C
close C
caught

The exception broke off the body of the block, but the door closed anyway. And it closed before the catch ran: Java first closes the resources and then looks for whoever will answer the alarm.

Here the door-closer picture is imprecise. A real door closes as soon as you have walked through. A resource closes only at the end of the whole try block, and inside the block you can work with it.

Common mistake

The door got its close() method, but the interface was forgotten:

JAVA
record Door(String name) { // ✗
    public void close() {
        System.out.println("close " + name);
    }
}
TEXT
error: incompatible types: try-with-resources not applicable to variable type

A program with try (Door door = new Door("A")) does not compile, although the door has a close() method. The compiler looks not at the method but at the type: only an AutoCloseable may go into the parentheses of try. It reports the error at the try line and adds Door cannot be converted to AutoCloseable, but the fix belongs in the record's header: record Door(String name) implements AutoCloseable.

Key points

  • try-with-resources calls close() on each resource by itself whichever way the block is left.
  • A resource is an object of a class that implements AutoCloseable.
  • Several resources close in reverse order: the last one opened closes first.
  • On an exception, the resources close before catch runs.