Try-with-resources

Basic Java
≈ 3 min read

Why try-with-resources is needed

Some objects hold a resource that must be released after use. If you forget to do that, the resource may remain occupied longer than necessary. Closing can be organized with finally, but Java has a shorter and safer construct for this task — try-with-resources.

try (Session session = new Session()) {
    session.send("Hello");
}

When execution leaves the try block, Java automatically calls session.close(). This happens both when the block finishes normally and when an exception occurs inside it. A separate finally just to close the resource is not needed.

Which objects can be used

A resource inside the parentheses must implement the AutoCloseable interface. That means your own class can also be a resource:

public class Session implements AutoCloseable {

    public void send(String message) {
        System.out.println(message);
    }

    @Override
    public void close() {
        System.out.println("Session closed");
    }
}

The AutoCloseable interface defines the close() method. For try-with-resources, this contract is what matters: when the block is exited, the construct calls the closing method automatically.

try-with-resources does not destroy the object. The construct only guarantees a call to its close(). What actually happens during closing is defined by the resource class itself.

Multiple resources

A single try can open multiple resources, separated by semicolons:

try (FirstResource first = new FirstResource();
     SecondResource second = new SecondResource()) {
    work(first, second);
}

They are closed in reverse order: first second, then first. This is especially important when one resource depends on another while it is being used.

When the resource already exists

In modern Java, a resource does not have to be created directly inside the parentheses. If a local variable is final or effectively final, it can be used directly:

Session session = new Session();

try (session) {
    session.send("Hello");
}

Effectively final means that the variable is not assigned another value after its initial assignment. If session is reassigned later, it can no longer be used in this form of try-with-resources.

When errors happen both during work and closing

Sometimes an exception occurs inside the try block, and then the close() method throws another exception. Java does not replace the original error with the closing error: the exception from the body of try remains the primary one, while the exception from close() is stored as a suppressed exception.

You can obtain such exceptions through getSuppressed(). This way, try-with-resources does not lose important information even when problems occur in two places at once.