Java: try-with-resources

A try-with-resource statement automatically closes a “resource” after it has been used. A resource could for instance be a file, stream, reader, writer or socket. Technically it’s anything implementing the AutoCloseable interface.

try (FileWriter w = new FileWriter("file.txt")) {
    w.write("Hello World");
}
// w.close() is called automatically

In the above example, w.close() is called regardless if w.write(...) throws an exception or not. Conceptually it’s similar to adding w.close() in a finally block.

Multiple Resources

You can use multiple resources in a single try-with-resource by separating the declarations with ; as follows:

// Copy one byte from src.txt to dst.txt
try (FileReader fr = new FileReader("src.txt");
     FileWriter fw = new FileWriter("dst.txt")) {
    fw.write(fr.read());
}

The resources are closed in the reversed order of declarations. In the example above, fw would be closed first, then fr.

Exceptions

In the example at the top of this article an IOException may be thrown by

  • new FileWriter("file.txt")
  • w.write("Hello World")
  • The implicit call to w.close()

If the constructor throws an exception, there will be no object to call close on, so the exception propagates without further action:

try (FileWriter w = new FileWriter("file.txt")) { w.write("Hello World"); } // no call to w.close()

If the call to w.write throws an exception, w.close() will be called, and then the exception will propagate:

try (FileWriter fw = new FileWriter("file.txt")) { w.write("Hello World"); } // Implicit call to w.close()

If the implicit call to w.close() throws an exception then this exception propagates:

try (FileWriter fw = new FileWriter("file.txt")) { w.write("Hello World"); } // Implicit call to w.close()

Suppressed Exceptions

Another possibility is that w.write throws an exception, and then the implicit call to w.close also throws an exception. In this case the first exception “wins” and the second exception is suppressed.

try (FileWriter fw = new FileWriter("file.txt")) { w.write("Hello World"); } // Implicit call to w.close() w.close exception suppressed w.write exception propagates

Custom AutoCloseable implementation

You can roll your own AutoCloseable implementation as well:

class MyResource implements AutoCloseable {
    @Override
    public void close() {
        System.out.println("Closing resource");
    }
}

class Example {
    public static void main(String[] args) {
        try (MyResource r = new MyResource()) {
            System.out.println("Using resource");
        }
    }
}

Output:

Using resource
Closing resource

Since AutoCloseable is a functional interface, you can initialize it using a lambda:

try (AutoCloseable r = () -> System.out.println("Closing")) {
    // ...
}

Comments

Be the first to comment!