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:
If the call to w.write
throws an exception, w.close()
will be called, and then the exception will propagate:
If the implicit call to w.close()
throws an exception then this exception propagates:
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.
For details, se separate article: Suppressed Exceptions.
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")) {
// ...
}