What is try-with-resources?
Previously you had to manually close resources in finally:
Junior Level
Definition
Try-with-resources (TWR) - a Java 7+ construct. Minimum version: Java 7. For Java 6 and below - use finally. In Android - API 19+ (KitKat). Automatically closes resources after exiting the try block.
Why it’s needed
Previously you had to manually close resources in finally:
// Old approach (before Java 7)
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("file.txt"));
br.readLine();
} finally {
if (br != null) br.close(); // Manually!
}
Now automatic:
// Modern approach (Java 7+)
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
br.readLine();
} // br.close() is called automatically!
Which resources can be used
Any that implement AutoCloseable:
FileInputStream,BufferedReader- filesConnection,Statement- databaseSocket- network
Multiple resources
try (FileInputStream fis = new FileInputStream("in.txt");
FileOutputStream fos = new FileOutputStream("out.txt")) {
// Both will be closed automatically
}
When NOT to use try-with-resources
- Factory methods - you create a resource and return it to the caller (TWR will close it before return)
- Resource lives longer than one method - lifecycle is managed externally
- Pooled resources (HikariCP connection) - return to pool != closing, pool manages itself
Middle Level
How it works
The compiler expands TWR into code with finally and suppressed exception handling:
// Your code
try (Resource r = new Resource()) {
r.doWork();
}
// Compiler creates this template to:
// (1) guarantee resource closing
// (2) not lose exception from close() if there was already an error in try
// -- it's added to the suppressed list of primaryException
// Expands to:
Resource r = new Resource();
Throwable primaryException = null;
try {
r.doWork();
} catch (Throwable t) {
primaryException = t;
throw t;
} finally {
if (r != null) {
if (primaryException != null) {
try { r.close(); }
catch (Throwable t) { primaryException.addSuppressed(t); }
} else {
r.close();
}
}
}
Suppressed Exceptions
If exception #1 was thrown in try, and exception #2 during close():
- #1 remains the main one
- #2 is added as suppressed
- You get the full picture:
Error A (Suppressed: Error B)
Get suppressed: exception.getSuppressed()
Nested resource trap effect
// DANGEROUS - FileWriter may leak!
try (BufferedWriter writer = new BufferedWriter(new FileWriter("file.txt"))) {
// If BufferedWriter's constructor throws, FileWriter will NOT close
}
// SAFE - each resource separately
try (FileWriter fw = new FileWriter("file.txt");
BufferedWriter writer = new BufferedWriter(fw)) {
writer.write("data");
}
Java 9+ - effectively final
You can use external variables:
BufferedReader br = createReader();
try (br) { // br is effectively final
br.readLine();
}
Senior Level
Close order (LIFO)
Resources are closed in the reverse order of their declaration:
LIFO (Last In, First Out) - last opened, first closed. Like a stack of plates: last one you put - first one you take. For resources this means: the most “inner” resource is closed first.
try (Socket socket = new Socket("localhost", 8080);
OutputStream os = socket.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os))) {
// Will close: writer -> os -> socket
}
This is critical for stream stacks. If you close Socket before Stream, Stream will fail on flush attempt.
Null Resources
If a resource in parentheses is initialized as null, TWR simply ignores it - no NPE.
Performance: Suppressed Overhead
When closing 1000 resources with mass failure, the main exception object contains a huge suppressed list. This can hit memory.
Edge Cases
- Catch/Finally order - your
catchandfinallyexecute after resources are closed - Inside
catch, resources are already unavailable (closed) - Compiler creates a hidden local variable for external resources (Java 9+)
Diagnostics
Throwable.getSuppressed()- always check this array for infrastructure issues- Static Analysis - SonarLint finds resources created inside
tryblock but not in parentheses javap -v- see generated bytecode to understand the mechanism
Interview Cheat Sheet
Must know:
- Try-with-resources (TWR) - Java 7+, automatically closes resources after exiting
try - Resource must implement
AutoCloseable - Compiler expands TWR to
finallywith suppressed exception handling - Suppressed exceptions: if both
tryandclose()failed - #1 is main, #2 is suppressed - Close order - LIFO (last opened, first closed)
- Nested resource trap effect:
new B(new A())- if B fails, A leaks - Java 9+ supports effectively final external variables
- Null resource in TWR is simply ignored - no NPE
Frequent follow-up questions:
- Why are nested resources dangerous? - If outer resource’s constructor fails, inner one leaks; declare each separately
- In what order are resources closed? - LIFO: last declared is closed first
- What happens if resource = null? - TWR ignores it, no NPE
- When NOT to use TWR? - Factory methods (return from method), pooled resources, resource lives longer than method
Red flags (NOT to say):
- “I create resources inside try but not in parentheses” - they won’t close automatically
- “Suppressed exceptions don’t matter on mass failure” - they can contain critical diagnostics
- “TWR only works with InputStream” - works with any AutoCloseable
Related topics:
- [[What are the requirements for resources in try-with-resources]]
- [[What is the AutoCloseable interface]]
- [[What is the difference between AutoCloseable and Closeable]]
- [[What are suppressed exceptions]]
- [[Is the execution of a finally block guaranteed]]