Java 42: try-with-resources & AutoCloseable
easy⏱ 5 mincoursejava
The construct
try (var r = open()) { use(r); } — any resource declared in the parens that implements AutoCloseable (or Closeable, which narrows close() to throw IOException) is closed automatically when the block exits, normally or exceptionally. Multiple resources are separated by ; and closed in reverse declaration order.
try (var in = new FileInputStream("a");
var out = new FileOutputStream("b")) {
in.transferTo(out);
} // out.close() then in.close() — reverse order, guaranteed
Suppressed exceptions
If the try body throws and a close() also throws, the body's exception wins (propagates) and the close() exception is suppressed — attached via Throwable.addSuppressed(...) and reachable through getSuppressed(). This is the opposite of the old finally idiom, where a close() failure would mask the real error. try-with-resources never loses the primary exception.
Effectively-final resources (Java 9)
Java 9 lets you reference an already-declared effectively final variable in the resource list: try (existing) { ... }. The resource doesn't have to be declared inside the parens anymore — handy when the resource came from elsewhere but you still want guaranteed closing.
Build a closing tracer
Implement Resource with close() pushing its name onto a shared closed[] log. Wrap a tryWith([a, b, c], body) helper that closes them in reverse order in a finally, even if body throws. Then make one resource's close() throw and the body throw too — collect the body error as primary and the close error in a suppressed list. Verify close order is c, b, a.
Implement AutoCloseable for your own handles
Any wrapper around a socket, lock, transaction, or temp file should implement AutoCloseable so callers get try-with-resources for free. Make close() idempotent (safe to call twice) and avoid throwing from it when you can — a throwing close() complicates every call site.
Quiz: close order with two resources
try (var a = open(); var b = open()) — in what order do they close? b first, then a — reverse of acquisition, like nested constructors/destructors. This matters when b depends on a (e.g. a buffered writer wrapping a file stream): the dependent must close before the thing it depends on.