DEV Community

DHRUV AHIR
DHRUV AHIR

Posted on

Stop Writing Clunky Finally Blocks: Clean Java File Handling with Try-with-Resources

When working with files,network sockets,or database connections in Java, forgetting to close a resource is one of the most common causes of memory and file-descriptor leaks.

For years,developers relied on manual cleanup inside a finally block. While it works, it leads to bloated, nested code that is prone to subtle bugs.Here is why the old way is risky, and how Java's try-with-resources solves it cleanly.

The Clunky Way: Manual Cleanup in finally

In older Java code, closing a stream required nested try-catch blocks inside finally:

public static void riskyRead(String filename) {
    BufferedReader reader = null;
    try {
        reader = new BufferedReader(new FileReader(filename));
        System.out.println("Reading line: " + reader.readLine());
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (reader != null) {
                reader.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Enter fullscreen mode Exit fullscreen mode

Why this is problematic:

  1. Verbose Boilerplate: Over half the function exists just to close a single stream safely.
  2. Suppressed Exceptions: If an exception occurs in both the try block and the finally block, the exception in finally overwrites the original error, making debugging significantly harder.

The Modern Way: try-with-resources

Introduced in Java 7, try-with-resources automatically handles closing any resource that implements java.lang.AutoCloseable.

Here is the exact same logic written cleanly:

public static void safeRead(String filename) {
    try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
        System.out.println("Safe reading line: " + reader.readLine());
    } catch (IOException e) {
        System.err.println("Failed to read file: " + e.getMessage());
    }
}
Enter fullscreen mode Exit fullscreen mode

What happens behind the scenes:

  • The resource (BufferedReader) is initialized inside parentheses directly after try.
  • As soon as execution leaves the block—whether normally or via an exception—the JVM automatically invokes reader.close().
  • If both the read operation and the auto-close fail, Java preserves the original exception and attaches the secondary error via suppressed exceptions.

Complete Runnable Example

Runnable companion code available on GitHub.

Whenever you deal with I/O streams, database connections, or network sockets, verify if the class implements AutoCloseable. If it does, always wrap it in try-with-resources to eliminate resource leaks and unneeded boilerplate.

Top comments (0)