Try-With-Resources
Automatically close resources like streams and connections using the try-with-resources statement.
Overview
Key Points
- •Syntax: try (ResourceType r = new ResourceType()) { ... }
- •The resource must implement AutoCloseable (or its subinterface Closeable)
- •close() is called automatically when the try block exits, whether normally or via exception
- •Multiple resources can be declared, separated by semicolons. They are closed in reverse order
- •Exceptions from close() are suppressed if an exception was already thrown in the try body; access them with getSuppressed()
- •You can create your own AutoCloseable classes
Examples
Basic try-with-resources with a custom resource
public class Main {
static class DatabaseConnection implements AutoCloseable {
private final String url;
DatabaseConnection(String url) {
this.url = url;
System.out.println("Opened connection to " + url);
}
String query(String sql) {
System.out.println("Running query: " + sql);
return "result";
}
@Override
public void close() {
System.out.println("Closed connection to " + url);
}
}
public static void main(String[] args) {
// Connection is closed automatically after the block
try (DatabaseConnection conn = new DatabaseConnection("localhost/mydb")) {
String result = conn.query("SELECT * FROM users");
System.out.println("Got: " + result);
}
// close() was called here
System.out.println("After try block");
}
}close() is called after the try block regardless of whether an exception occurred. The output will always show "Closed connection" before "After try block".
Multiple resources and exception handling
public class Main {
static class Resource implements AutoCloseable {
final String name;
Resource(String name) {
System.out.println("Opening " + name);
this.name = name;
}
void use() {
System.out.println("Using " + name);
if (name.equals("Unstable")) {
throw new RuntimeException(name + " failed!");
}
}
@Override
public void close() {
System.out.println("Closing " + name);
}
}
public static void main(String[] args) {
// Multiple resources: opened in order, closed in REVERSE order
try (Resource r1 = new Resource("Database");
Resource r2 = new Resource("Unstable")) {
r1.use();
r2.use(); // throws
} catch (RuntimeException e) {
System.out.println("Caught: " + e.getMessage());
}
}
}Resources are closed in reverse order of declaration. Even when r2.use() throws, both r2 and r1 are closed before the catch block runs.
Suppressed exceptions
public class Main {
static class Leaky implements AutoCloseable {
Leaky() { System.out.println("Opened"); }
void doWork() { throw new RuntimeException("Work failed"); }
@Override
public void close() { throw new RuntimeException("Close failed too"); }
}
public static void main(String[] args) {
try (Leaky r = new Leaky()) {
r.doWork();
} catch (RuntimeException e) {
System.out.println("Primary: " + e.getMessage());
for (Throwable suppressed : e.getSuppressed()) {
System.out.println("Suppressed: " + suppressed.getMessage());
}
}
}
}When both the body and close() throw, the body exception is primary and the close() exception is attached as a suppressed exception. getSuppressed() returns them.
Common Mistakes
- Using a manual try-finally to close resources instead of try-with-resources. The finally approach is error-prone: if both the body and finally throw, the body exception is lost
- Storing the resource in a variable before the try: InputStream in = new FileInputStream(f); try (InputStream x = in) { ... } is fine, but try { ... } finally { in.close(); } is the old pattern to replace
- Forgetting that the resource variable is effectively final inside the try block. You cannot reassign it
Note
Use try-with-resources for everything that is closeable: file streams, HTTP connections, database connections, ZIP files, and any class you write that holds an external resource. It is always safer than manual close().
Exercises
Write Java code and click Run to execute it instantly. When your output looks correct, mark as done.
Completed: 0 / 4 exercises
Knowledge Check
Question 1 of 4