Java
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Object-Oriented Java
-
Section 4: Collections Framework
-
Section 5: Exception Handling
-
Section 6: Generics
-
Section 7: Functional Java
-
Section 8: Concurrency
-
Section 9: I/O and NIO
-
Section 10: JVM Internals
-
Section 11: Modern Java Features
-
Section 12: Build Tools and Project Structure
-
Section 13: Testing
-
Section 14: Databases and Persistence
-
Section 15: Networking
-
Section 16: Design and Best Practices
-
Section 17: Reflection and Annotations
-
Section 18: Logging and Diagnostics
-
Section 19: Date, Time, and Internationalization
-
Section 20: Java Platform Module System
-
Section 21: Security in Java
-
Section 22: Advanced Collections and Data Structures
-
Section 23: More Concurrency Patterns
-
Section 24: Compression, Files, and System Integration
-
Section 25: GUI Programming
-
Section 26: Practical Projects
-
Section 27: Data Structures and Algorithms
-
Section 28: Interview and Algorithm Practice
-
Section 29: JSON and Data Interchange
-
Section 30: More Concurrency Utilities
-
Section 31: More Collections and Streams Practice
-
Section 32: More File and System Programming
-
Section 33: Standard Library Deep Dive
-
Section 34: More Practice and Drills
-
Section 35: More Testing and Quality
-
Section 36: More Design Patterns and Architecture
-
Section 37: Career and Ecosystem
-
Section 38: More OOP and Architecture Practice
-
Section 39: More Enterprise Concepts
-
Section 40: Advanced JavaFX
-
Section 41: More Interview Practice
55: Try-With-Resources
I want to show you something that used to be a huge pain in the neck for all of us Java developers. We're going to look at how we handle "resources"—things like file handles, database connections, or network sockets—that the operating system expects us to close when we're done. If we don't, we get resource leaks, and eventually, the app crashes because it can't open any more files.
The "I'll just close it at the end" mistake
Let's start with a simple task: reading a small configuration file called app.properties. I'll write it the way a beginner might, just opening the stream and reading the line.
public void readConfig() {
try {
BufferedReader reader = new BufferedReader(new FileReader("app.properties"));
System.out.println(reader.readLine());
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
At first glance, this looks fine. I open it, read it, and close it. But here's the problem: what happens if readLine() throws an exception? The execution jumps straight to the catch block. The reader.close() line is skipped entirely. The file stays open in the background. Do this a few thousand times in a production server, and your system will run out of file descriptors.
Fighting the Boilerplate
To fix that, the "old school" Java way was to use a finally block. The finally block is guaranteed to run regardless of whether an exception was thrown or not. Let's try that.
public void readConfig() {
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader("app.properties"));
System.out.println(reader.readLine());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Stop and look at that. It's hideous. I had to declare the variable outside the try block so it was in scope for the finally block. Then, because close() itself can throw an IOException, I had to wrap the close call in another try-catch. This is what we call "boilerplate"—code that you have to write over and over again, but it doesn't actually add any business value. It just exists to satisfy the compiler.
Letting Java handle the cleanup
Around Java 7, the language designers realized we were all tired of writing this nonsense. They introduced try-with-resources. The trick is that you can actually declare and initialize your resource inside parentheses immediately after the try keyword.
Let's rewrite that same logic:
public void readConfig() {
try (BufferedReader reader = new BufferedReader(new FileReader("app.properties"))) {
System.out.println(reader.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
That's it. No finally block. No nested try-catches. The magic here is that Java automatically calls .close() on the reader the moment the try block finishes, whether it finished successfully or crashed with an exception.
You might be wondering: "How does Java know it's supposed to close this specific object?" The answer is the AutoCloseable interface. Any class that implements AutoCloseable (which almost every resource class in the JDK does) can be used in a try-with-resources statement. If you ever write your own class that manages a heavy resource—like a custom connection to a piece of hardware—make sure you implement AutoCloseable so your teammates can use this syntax too.
Handling multiple resources
One last thing: what if you need to read from one file and write to another? You don't need nested try-with-resources. You can just separate the resources with a semicolon inside those parentheses.
try (BufferedReader reader = new BufferedReader(new FileReader("input.txt"));
BufferedWriter writer = new BufferedWriter(new FileWriter("output.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
writer.write(line);
writer.newLine();
}
} catch (IOException e) {
e.printStackTrace();
}
Java will close these in the reverse order they were opened. It's clean, it's safe, and it keeps your code from looking like a pyramid of curly braces.
📋 Practical Task
Exercise: Secure Log File Archiver
You need to create a utility method that copies the contents of a log file (system.log) to a backup file (system.log.bak).
- Write a method called
archiveLog(). - Use a try-with-resources block to open a
BufferedReaderfor the source file and aBufferedWriterfor the destination file. - Read the source file line by line and write each line to the backup file.
- Ensure that you handle
IOExceptionproperly. - Do NOT use a
finallyblock to close the streams; let the try-with-resources handle it.
There are no comments for now.