try-with-resources in Java – Explained with Examples
Files, network sockets, database connections and streams hold operating-system resources that must be closed when you are done, even if something goes wrong. try-with-resources, introduced in Java 7, closes such resources automatically at the end of a try block. It replaces long, error-prone try-finally code with a single clear statement.
This tutorial shows how to use try-with-resources, how several resources are closed, what happens to exceptions thrown while closing, and how to make your own classes work with it.
1. Syntax
try (ResourceType resource = new ResourceType(...)) {
// use the resource
} // resource.close() is called automatically here
try (A a = ...; B b = ...) { // several resources, separated by semicolons
...
} catch (SomeException e) { // catch and finally are optional
...
}
Any object whose class implements java.lang.AutoCloseable (or its sub-interface java.io.Closeable) can be declared in the parentheses.
2. Reading a File Safely
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class ReadFileDemo {
public static void main(String[] args) throws IOException {
Path file = Files.createTempFile("notes", ".txt");
Files.writeString(file, "first line\nsecond line\nthird line\n");
// The reader is closed automatically at the end of the try block
try (BufferedReader reader = Files.newBufferedReader(file)) {
String line;
int n = 1;
while ((line = reader.readLine()) != null) {
System.out.println(n++ + ": " + line);
}
} catch (IOException e) {
System.out.println("Could not read file: " + e.getMessage());
}
Files.delete(file);
}
}
1: first line 2: second line 3: third line
The reader is closed when the try block ends, whether the loop finishes normally or an exception is thrown. No finally block or null checks are needed.
3. Multiple Resources and Closing Order
Resources are opened in the order they are declared and closed in the reverse order, so a resource is always closed before the ones it might depend on:
public class CloseOrder {
static class Resource implements AutoCloseable {
private final String name;
Resource(String name) { this.name = name; System.out.println("open " + name); }
void use() { System.out.println("use " + name); }
@Override public void close() { System.out.println("close " + name); }
}
public static void main(String[] args) {
try (Resource db = new Resource("database");
Resource file = new Resource("file");
Resource socket = new Resource("socket")) {
db.use();
file.use();
socket.use();
}
System.out.println("all resources closed (in reverse order)");
}
}
open database open file open socket use database use file use socket close socket close file close database all resources closed (in reverse order)
Implementing AutoCloseable is all it takes to make your own class work with try-with-resources.
4. Suppressed Exceptions
What if the try block throws an exception and then close() throws another one? With try-finally, the second exception would replace the first and the real cause would be lost. try-with-resources keeps the original exception and attaches the closing exception to it as a suppressed exception:
public class SuppressedExceptions {
static class FlakyResource implements AutoCloseable {
@Override public void close() {
throw new IllegalStateException("error while closing");
}
}
public static void main(String[] args) {
try (FlakyResource r = new FlakyResource()) {
throw new IllegalArgumentException("error while working");
} catch (Exception e) {
System.out.println("main exception: " + e.getMessage());
for (Throwable s : e.getSuppressed()) {
System.out.println("suppressed: " + s.getMessage());
}
}
}
}
main exception: error while working suppressed: error while closing
Stack traces print suppressed exceptions too, so no information is lost.
5. Old Style vs try-with-resources
import java.io.StringReader;
import java.io.BufferedReader;
import java.io.IOException;
public class OldStyleVsNew {
// Before Java 7: verbose and easy to get wrong
static String firstLineOld(String text) throws IOException {
BufferedReader reader = null;
try {
reader = new BufferedReader(new StringReader(text));
return reader.readLine();
} finally {
if (reader != null) {
reader.close();
}
}
}
// Java 7+: the same in a few lines
static String firstLineNew(String text) throws IOException {
try (BufferedReader reader = new BufferedReader(new StringReader(text))) {
return reader.readLine();
}
}
// Java 9+: an effectively final variable can be used directly
static String firstLineJava9(BufferedReader reader) throws IOException {
try (reader) {
return reader.readLine();
}
}
public static void main(String[] args) throws IOException {
String text = "hello\nworld";
System.out.println(firstLineOld(text));
System.out.println(firstLineNew(text));
System.out.println(firstLineJava9(new BufferedReader(new StringReader(text))));
}
}
hello hello hello
- The old style needs a variable outside the try, a
nullcheck and a finally block, and it loses the original exception ifclose()fails. - Since Java 9, an existing effectively final variable can be listed directly:
try (reader) { ... }.
6. AutoCloseable vs Closeable
AutoCloseable | Closeable | |
|---|---|---|
| Package | java.lang | java.io |
| Since | Java 7 | Java 5 |
close() throws | Exception | IOException |
| Calling close twice | May have side effects | Must have no effect (idempotent) |
| Typical implementations | JDBC Connection, ExecutorService (Java 19+), your own classes | Streams, readers, writers, channels |
7. Common Resources to Use It With
- File I/O:
FileInputStream,BufferedReader,Files.lines()streams,Scanneron a file. - JDBC:
Connection,PreparedStatement,ResultSet. - Networking:
Socket,ServerSocket, HTTP response bodies. - Concurrency:
ExecutorService(Java 19+), which waits for tasks when closed. - Locks and other custom resources, by wrapping them in an
AutoCloseable.
8. Rules and Tips
- Resources declared in the parentheses are implicitly
finaland are visible only inside the try block. - Resources are closed before any catch or finally block runs.
- If a resource initialiser throws, resources already opened are still closed.
- A resource that is
nullis simply skipped when closing. - Declare each resource separately; nesting constructors like
new BufferedReader(new FileReader(f))only registers the outer one (usually fine, because closing it closes the inner one).
9. Summary
- try-with-resources automatically closes
AutoCloseableresources at the end of the try block. - Multiple resources are closed in reverse order of declaration.
- Exceptions from
close()are attached to the main exception as suppressed exceptions. - It is shorter and safer than try-finally; Java 9 allows existing effectively final variables.
- Implement
AutoCloseableto make your own classes work with it.
Related Tutorials
Reference: Oracle Java Tutorials: The try-with-resources Statement
Frequently Asked Questions (FAQ)
Q1. What is try-with-resources in Java?
A form of the try statement (Java 7+) that declares resources in parentheses and closes them automatically when the try block finishes, even if an exception occurs.
Q2. Which objects can be used in try-with-resources?
Any object that implements java.lang.AutoCloseable, which includes all java.io.Closeable types such as streams, readers and writers.
Q3. In which order are multiple resources closed?
In reverse order of declaration: the last resource opened is closed first.
Q4. Do I still need a finally block?
Not for closing the declared resources. You can still add catch and finally blocks for other handling; they run after the resources are closed.
Q5. What is a suppressed exception?
An exception thrown while closing a resource after the try block already threw one. It is attached to the main exception and can be read with getSuppressed().
Q6. What is the difference between AutoCloseable and Closeable?
Closeable (java.io) extends AutoCloseable (java.lang). Closeable.close() throws only IOException and must be idempotent; AutoCloseable.close() may throw any Exception.
Q7. Can I use try-with-resources without catch?
Yes. If the method declares the checked exceptions with throws, a plain try (...) { } is enough.
Q8. What changed in Java 9?
You can reference an existing final or effectively final variable in the resource list (try (reader) { ... }) instead of declaring a new variable.
Q9. Are resources closed before the catch block runs?
Yes. By the time a catch or finally block runs, all resources of that try statement are already closed.
Q10. What if a resource is null?
No close() call is made for it, and no exception occurs.
Q11. Can I modify a resource variable inside the try block?
No. Resource variables are implicitly final, so they cannot be reassigned.
Q12. How do I make my own class work with try-with-resources?
Implement AutoCloseable (or Closeable) and put the release logic in close(). Narrow the throws clause if your close method cannot fail.
Q13. Can try-with-resources be used with JDBC?
Yes, and it is the recommended way: try (Connection c = ds.getConnection(); PreparedStatement ps = c.prepareStatement(sql); ResultSet rs = ps.executeQuery()) { ... }.
Q14. Why is try-with-resources better than try-finally?
It is shorter, never forgets to close, closes multiple resources in the right order, and keeps the original exception instead of losing it when close() fails.
Q15. Is Scanner closed by try-with-resources?
Yes, Scanner implements Closeable. Be careful with a Scanner on System.in: closing it also closes standard input for the rest of the program.
Q16. Can ExecutorService be used in try-with-resources?
Yes, since Java 19 it implements AutoCloseable. Its close() stops accepting tasks and waits for submitted tasks to finish.
Q17. Are resources closed if the constructor of a later resource throws?
Yes. Any resources that were already successfully created are closed, in reverse order, before the exception propagates.
Q18. Can I declare resources of different types?
Yes. Each declaration in the parentheses can have its own type, separated by semicolons.
Q19. Do Files.lines() streams need try-with-resources?
Yes. Streams created from files hold an open file handle, so use try (Stream<String> lines = Files.lines(path)) { ... }. Ordinary collection streams do not need closing.
Q20. When was try-with-resources introduced?
In Java 7 (2011), along with the AutoCloseable interface and suppressed exceptions.