How does try-with-resources work, and what interface must a resource implement?
Quick Answer
try-with-resources automatically closes any resource declared in its parentheses when the try block exits, whether normally or via an exception, without needing an explicit finally block. The resource must implement AutoCloseable (or its subtype Closeable), and resources are closed in the reverse order they were declared, even if closing one throws — that exception is added as a suppressed exception on the original.
Detailed Answer
Before Java 7, closing a resource safely required verbose, error-prone manual finally blocks:
FileReader fr = new FileReader("file.txt");
try {
// use fr
} finally {
fr.close(); // could itself throw, masking the original exception
}
try-with-resources (Java 7+) automates this: any resource declared in the parentheses is automatically closed when the block exits, in either the normal or exceptional path:
try (FileReader fr = new FileReader("file.txt");
BufferedReader br = new BufferedReader(fr)) {
System.out.println(br.readLine());
} // both br and fr are closed automatically, in reverse declaration order
The resource type must implement AutoCloseable (which declares void close() throws Exception), or its more specific subtype Closeable (void close() throws IOException, used by most I/O classes).
Closing order and suppressed exceptions: resources are closed in the reverse order they were declared (last-declared, first-closed). If the try block itself throws an exception, and closing a resource also throws, the close-time exception isn't lost — it's attached to the original exception as a suppressed exception, retrievable via Throwable.getSuppressed(), so no failure information is silently discarded.
Since Java 9, you can also use an effectively final variable declared outside the try directly in the parentheses, without redeclaring it:
BufferedReader br = new BufferedReader(new FileReader("file.txt"));
try (br) {
System.out.println(br.readLine());
}