Back to try-with-resources & Suppressed Exceptions
Q1Question 1 of 2

What is try-with-resources?

Key Concepts
  • try-with-resources (Java 7) automatically calls close() on any resource implementing AutoCloseable when the try block exits
  • Multiple resources are closed in REVERSE declaration order to respect dependency ordering
  • If both the try body and close() throw, the try body exception is primary and close() exception is suppressed via addSuppressed()
  • Eliminates the verbose finally-with-null-check pattern and prevents resource leaks by design
  • Java 9 allows effectively final variables in try-with-resources: try (existingReader) { }
  • Custom classes can implement AutoCloseable for any acquire-release pattern like locks, timers, and connections

Definition

try-with-resources (Java 7) automatically closes any resource that implements AutoCloseable when the try block exits, whether normally or via exception.
  • try-with-resources declares resources in the try parentheses: try (Resource r = new Resource()) { use(r); }. The resource's close() method is called automatically when the try block exits.
  • Multiple resources are closed in reverse declaration order: try (A a = ...; B b = ...) { } closes b first, then a. This respects dependency ordering (inner resources before outer).
  • Dual-exception handling: if both the try body and close() throw, the try body's exception is primary (propagated) and close()'s exception is suppressed (attached via addSuppressed()).
  • Any class implementing AutoCloseable (or its parent Closeable) works with try-with-resources.
  • Java 9 allows effectively final variables: BufferedReader r = ...; try (r) { } without re-declaring in the parentheses.

try-with-resources is like the automatic door at National Bank of India. When you walk out of the vault (try block exits), the door closes automatically, whether you walk out normally, run out because of a fire alarm (exception), or are escorted out (return). You do not need a security guard (finally block) standing there waiting to close it. Multiple doors close in reverse order: the inner vault door first, then the outer security door.

Understanding the Concepts

What is try-with-resources?

try-with-resources (Java 7) is a language feature that automatically closes resources when the try block exits. Any class implementing AutoCloseable can be declared in the try parentheses, and its close() method is called automatically.

JAVA
package com.bank.demo;

import java.io.BufferedReader;
import java.io.StringReader;

public class TryWithResourcesBasic {

    public static void main(String[] args) {
        String csvData = "SAV2001,50000\nCUR3001,75000";

        // Resource declared in try parentheses: auto-closed on exit
        try (BufferedReader reader = new BufferedReader(new StringReader(csvData))) {
            String line;
            while ((line = reader.readLine()) != null) {
                String[] parts = line.split(",");
                System.out.println("Account: " + parts[0] + ", Balance: Rs." + parts[1]);
            }
        } catch (Exception e) {
            System.out.println("Error: " + e.getMessage());
        }
        // reader.close() called automatically here.
        // No finally needed. No null check needed.
    }
}
TEXT
Account: SAV2001, Balance: Rs.50000
Account: CUR3001, Balance: Rs.75000

How are multiple resources closed?

Multiple resources are closed in reverse declaration order. This ensures inner (dependent) resources are released before outer resources.

JAVA
package com.bank.demo;

public class MultipleResourcesDemo {

    static class Connection implements AutoCloseable {
        Connection() { System.out.println("1. Connection opened"); }
        @Override public void close() { System.out.println("3. Connection closed (last)"); }
    }

    static class Statement implements AutoCloseable {
        Statement() { System.out.println("2. Statement created"); }
        @Override public void close() { System.out.println("2. Statement closed (second)"); }
    }

    static class ResultSet implements AutoCloseable {
        ResultSet() { System.out.println("3. ResultSet opened"); }
        @Override public void close() { System.out.println("1. ResultSet closed (first)"); }
    }

    public static void main(String[] args) {
        System.out.println("=== Opening ===");
        try (Connection conn = new Connection();
             Statement stmt = new Statement();
             ResultSet rs = new ResultSet()) {
            System.out.println("\n=== Using resources ===");
            System.out.println("Processing query results...\n");
        }
        System.out.println("\nResources closed in REVERSE order");
    }
}
TEXT
=== Opening ===
1. Connection opened
2. Statement created
3. ResultSet opened

=== Using resources ===
Processing query results...

1. ResultSet closed (first)
2. Statement closed (second)
3. Connection closed (last)

Resources closed in REVERSE order

How does try-with-resources compare to the old finally pattern?

The old pattern requires null checks, nested try-catch for close(), and 10+ lines of boilerplate. try-with-resources does the same in 3 lines.

JAVA
package com.bank.demo;

import java.io.BufferedReader;
import java.io.StringReader;

public class OldVsNewPattern {

    // OLD: verbose finally pattern (12 lines of boilerplate)
    public static void oldPattern() {
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new StringReader("SAV2001,50000"));
            System.out.println("Old: " + reader.readLine());
        } catch (Exception e) {
            System.out.println("Error: " + e.getMessage());
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (Exception e) {
                    System.out.println("Close failed: " + e.getMessage());
                }
            }
        }
    }

    // NEW: try-with-resources (4 lines, clean)
    public static void newPattern() {
        try (BufferedReader reader = new BufferedReader(new StringReader("CUR3001,75000"))) {
            System.out.println("New: " + reader.readLine());
        } catch (Exception e) {
            System.out.println("Error: " + e.getMessage());
        }
    }

    public static void main(String[] args) {
        oldPattern();
        newPattern();
    }
}
TEXT
Old: SAV2001,50000
New: CUR3001,75000

How do you create a custom AutoCloseable?

Any class that implements AutoCloseable works with try-with-resources. This is powerful for any acquire-release pattern.

JAVA
package com.bank.service;

public class DistributedLock implements AutoCloseable {
    private final String lockKey;
    private boolean acquired;

    public DistributedLock(String lockKey) {
        this.lockKey = lockKey;
        this.acquired = true;
        System.out.println("Lock acquired: " + lockKey);
    }

    public void doWork() {
        System.out.println("Working under lock: " + lockKey);
    }

    @Override
    public void close() {
        if (acquired) {
            acquired = false;
            System.out.println("Lock released: " + lockKey);
        }
    }

    public static void main(String[] args) {
        // Lock is always released, even if doWork() throws
        try (DistributedLock lock = new DistributedLock("SETTLEMENT_BATCH_001")) {
            lock.doWork();
        }
        System.out.println("After try block: lock guaranteed released");
    }
}
TEXT
Lock acquired: SETTLEMENT_BATCH_001
Working under lock: SETTLEMENT_BATCH_001
Lock released: SETTLEMENT_BATCH_001
After try block: lock guaranteed released

What changed in Java 9 for try-with-resources?

Java 9 allows effectively final variables to be used directly in try-with-resources without re-declaring them.

JAVA
package com.bank.demo;

import java.io.BufferedReader;
import java.io.StringReader;

public class Java9Enhancement {

    public static void main(String[] args) throws Exception {
        // Java 7-8: must declare resource in try parentheses
        // BufferedReader r = new BufferedReader(new StringReader("test"));
        // try (r) { }  // COMPILE ERROR in Java 7-8

        // Java 9+: effectively final variable works
        BufferedReader reader = new BufferedReader(new StringReader("FD4001,200000"));
        try (reader) {  // Valid in Java 9+
            System.out.println("Java 9: " + reader.readLine());
        }
        // reader.close() called automatically
    }
}
TEXT
Java 9: FD4001,200000

What are common mistakes with try-with-resources?

JAVA
package com.bank.demo;

public class TryWithResourcesMistakes {

    static class LeakyResource implements AutoCloseable {
        LeakyResource() { System.out.println("Resource opened"); }
        @Override public void close() { System.out.println("Resource closed"); }
    }

    // WRONG: resource declared outside try, no auto-close
    public static void wrongOutside() throws Exception {
        LeakyResource r = new LeakyResource();
        try {
            System.out.println("Wrong: resource not in try parentheses");
        } finally {
            r.close();  // Manual close needed, verbose
        }
    }

    // CORRECT: resource in try parentheses
    public static void correctInside() {
        try (LeakyResource r = new LeakyResource()) {
            System.out.println("Correct: auto-close guaranteed");
        }
    }

    public static void main(String[] args) throws Exception {
        wrongOutside();
        System.out.println();
        correctInside();
    }
}
TEXT
Resource opened
Wrong: resource not in try parentheses
Resource closed

Resource opened
Correct: auto-close guaranteed
Resource closed

What should a senior engineer know?

  • AutoCloseable vs Closeable. Closeable extends AutoCloseable and restricts close() to throw IOException. AutoCloseable.close() can throw any Exception. Both work with try-with-resources.
  • Connection pooling. When using HikariCP or similar pools, connection.close() returns the connection to the pool rather than physically closing it. try-with-resources still works correctly.
  • Suppressed exceptions. If multiple resources each fail on close, each failure is added as a separate suppressed exception to the primary. All are visible in the stack trace.
  • Spring's JdbcTemplate. Spring manages connections internally, so you do not use try-with-resources for connections obtained through JdbcTemplate. But for raw JDBC, try-with-resources is essential.

What are common interview follow-up questions?

  • Can try-with-resources have a catch block? (Yes, catch and finally are both optional additions.)
  • Can try-with-resources have no catch or finally? (Yes, try (Resource r = ...) { } is valid by itself.)
  • What interface must a resource implement? (AutoCloseable or Closeable.)
  • In what order are multiple resources closed? (Reverse declaration order.)
  • What happens if close() throws? (It becomes a suppressed exception if try also threw.)

Visual Overview

DIAGRAM
  try (A a = new A(); B b = new B()) {
      use(a, b);
  }

  Execution:
  1. Open A
  2. Open B
  3. Execute try body
  4. Close B (reverse order, inner first)
  5. Close A (reverse order, outer second)

  If try throws + close throws:
  ┌────────────────────────────────────────┐
  │ try body exception  = PRIMARY          │
  │ close() exception   = SUPPRESSED       │
  │ Both visible in stack trace            │
  │ Access: e.getSuppressed()              │
  └────────────────────────────────────────┘

Key Takeaway

try-with-resources (Java 7) automatically closes any resource implementing AutoCloseable when the try block exits. You declare the resource in the try parentheses and the JVM calls close() automatically, whether the block completes normally, throws an exception, or returns early. Multiple resources are closed in reverse declaration order, ensuring inner resources are released before outer ones.

The key advantage over the old finally pattern is dual-exception handling. If both the try body and close() throw, the try body's exception is primary and close()'s is suppressed via addSuppressed(). Both are visible in the stack trace. In the old pattern, a throw in finally silently destroyed the try exception.

In the banking service at National Bank of India, Rajesh uses custom AutoCloseable implementations for distributed locks, metric timers, and transaction scopes. try (var lock = new SettlementLock("BATCH-001")) { settle(); } guarantees the lock is released even if settlement throws. Before try-with-resources, developers forgot to release locks in catch blocks, and 100 failed settlements exhausted the lock pool.

Remember one sentence: try-with-resources guarantees resource cleanup by automatically calling close() in reverse order when the try block exits.

---

Share
Use ← → arrow keys to navigate