try-with-resources
Motivation
Before Java 7, closing resources required verbose finally blocks prone to bugs:
javaInputStream in = null;
try {
in = new FileInputStream("file.txt");
// use in
} finally {
if (in != null) in.close(); // close() itself could throw!
}try-with-resources Syntax
Resources declared in the try(...) header are automatically closed when the block exits — whether normally or with an exception:
javatry (InputStream in = new FileInputStream("file.txt")) {
// use in
} // in.close() called automatically hereMultiple resources — closed in reverse declaration order:
javatry (
Connection conn = dataSource.getConnection();
PreparedStatement ps = conn.prepareStatement(sql)
) {
ps.execute();
} // ps closed first, then connAutoCloseable
Any class whose close() method should be called automatically must implement AutoCloseable (or its subinterface Closeable):
javapublic class Timer implements AutoCloseable {
private final long start = System.currentTimeMillis();
@Override
public void close() {
System.out.println("Elapsed: " + (System.currentTimeMillis() - start) + "ms");
}
}
try (var t = new Timer()) {
doWork();
} // prints elapsed time automaticallyCloseable (used by I/O classes) is a subinterface of AutoCloseable that restricts close() to throwing only IOException.
Suppressed Exceptions
If the try body throws and close() also throws, the close exception is suppressed — attached to the primary exception rather than replacing it:
javatry (var r = new BrokenResource()) {
throw new RuntimeException("primary");
// r.close() also throws — suppressed, not lost
}javatry {
// ...
} catch (Exception e) {
for (Throwable suppressed : e.getSuppressed()) {
System.out.println("Suppressed: " + suppressed);
}
}This is the opposite of finally — in finally, the secondary exception wins and the primary is lost.
Effectively Final Resources (Java 9+)
A variable declared before the try can be used as a resource if it is effectively final:
javavar conn = dataSource.getConnection();
try (conn) { // valid — conn is effectively final
conn.execute(sql);
}Combining with catch and finally
catch and finally can be added after the resource list. Resources are closed before catch runs:
javatry (var reader = Files.newBufferedReader(path)) {
process(reader);
} catch (IOException e) {
System.err.println("Failed: " + e.getMessage());
} finally {
System.out.println("Done");
}
// Close order: reader → catch (if needed) → finallyKey Rules
| Rule | Detail |
|---|---|
AutoCloseable |
Required to use in try-with-resources |
| Close order | Reverse declaration order |
| Suppressed exceptions | Close exceptions attached to primary, not lost |
| Effectively final | Pre-declared resources allowed since Java 9 |
null resource |
If a resource variable is null, close() is not called (no NPE) |