You open a file, read it, then must close it. Forgetting to close leaks resources. Try-with-resources automatically closes resources when done - even if exceptions occur. No more manual finally blocks for cleanup.

Basic syntax

Declare resources in try parentheses.

triggerError
BasicSyntax.java
Replay: real traced execution (multi-file project)
// Basic Try-with-Resources Syntax

public class BasicSyntax {
    public static void main(String[] args) {
        System.out.println("=== Basic Try-with-Resources ===\n");

        // Simple example with custom resource
        System.out.println("--- Simple Resource ---");

        try (SimpleResource resource = new SimpleResource("myResource")) {
            resource.doWork();
            System.out.println("Work completed");
        } // close() called automatically here

        System.out.println("After try block\n");

        // With catch block
        System.out.println("--- With Catch Block ---");

        boolean triggerError = true;
        try (SimpleResource resource = new SimpleResource("errorResource")) {
            resource.doWork();
            if (triggerError) {
                resource.causeError();
            }
        } catch (RuntimeException e) {
            System.out.println("Caught: " + e.getMessage());
        }

        System.out.println("Resource was still closed!\n");

        // With finally block
        System.out.println("--- With Finally Block ---");

        try (SimpleResource resource = new SimpleResource("finallyResource")) {
            resource.doWork();
        } finally {
            System.out.println("Finally block runs AFTER close()");
        }

        // Comparison with old style
        System.out.println("\n--- Old Style (Don't Do This) ---");
        oldStyleExample();

        System.out.println("\n=== Key Points ===");
        System.out.println("""
            1. Resource declared in try() parentheses
            2. Must implement AutoCloseable
            3. Automatically closed when try block exits
            4. Closed even if exception occurs
            5. catch and finally blocks are optional
            6. close() called BEFORE finally block
            """);
    }

    static void oldStyleExample() {
        SimpleResource resource = null;
        try {
            resource = new SimpleResource("oldStyle");
            resource.doWork();
        } finally {
            if (resource != null) {
                resource.close();
            }
        }
    }
}

// Simple AutoCloseable resource
class SimpleResource implements AutoCloseable {
    private final String name;
    private boolean closed = false;

    public SimpleResource(String name) {
        this.name = name;
        System.out.println("  [" + name + "] Resource opened");
    }

    public void doWork() {
        if (closed) throw new IllegalStateException("Resource is closed");
        System.out.println("  [" + name + "] Doing work...");
    }

    public void causeError() {
        throw new RuntimeException("Something went wrong!");
    }

    @Override
    public void close() {
        if (!closed) {
            closed = true;
            System.out.println("  [" + name + "] Resource closed");
        }
    }
}

//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
// Basic Try-with-Resources Syntax

public class BasicSyntax {
    public static void main(String[] args) {
        System.out.println("=== Basic Try-with-Resources ===\n");

        // Simple example with custom resource
        System.out.println("--- Simple Resource ---");

        try (SimpleResource resource = new SimpleResource("myResource")) {
            resource.doWork();
            System.out.println("Work completed");
        } // close() called automatically here

        System.out.println("After try block\n");

        // With catch block
        System.out.println("--- With Catch Block ---");

        boolean triggerError = false;
        try (SimpleResource resource = new SimpleResource("errorResource")) {
            resource.doWork();
            if (triggerError) {
                resource.causeError();
            }
        } catch (RuntimeException e) {
            System.out.println("Caught: " + e.getMessage());
        }

        System.out.println("Resource was still closed!\n");

        // With finally block
        System.out.println("--- With Finally Block ---");

        try (SimpleResource resource = new SimpleResource("finallyResource")) {
            resource.doWork();
        } finally {
            System.out.println("Finally block runs AFTER close()");
        }

        // Comparison with old style
        System.out.println("\n--- Old Style (Don't Do This) ---");
        oldStyleExample();

        System.out.println("\n=== Key Points ===");
        System.out.println("""
            1. Resource declared in try() parentheses
            2. Must implement AutoCloseable
            3. Automatically closed when try block exits
            4. Closed even if exception occurs
            5. catch and finally blocks are optional
            6. close() called BEFORE finally block
            """);
    }

    static void oldStyleExample() {
        SimpleResource resource = null;
        try {
            resource = new SimpleResource("oldStyle");
            resource.doWork();
        } finally {
            if (resource != null) {
                resource.close();
            }
        }
    }
}

// Simple AutoCloseable resource
class SimpleResource implements AutoCloseable {
    private final String name;
    private boolean closed = false;

    public SimpleResource(String name) {
        this.name = name;
        System.out.println("  [" + name + "] Resource opened");
    }

    public void doWork() {
        if (closed) throw new IllegalStateException("Resource is closed");
        System.out.println("  [" + name + "] Doing work...");
    }

    public void causeError() {
        throw new RuntimeException("Something went wrong!");
    }

    @Override
    public void close() {
        if (!closed) {
            closed = true;
            System.out.println("  [" + name + "] Resource closed");
        }
    }
}

//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
  1. public static void main(String[] args)

    3public class BasicSyntax {4    public static void main(String[] args) {5        System.out.println("=== Basic Try-with-Resources ===\n");67        // Simple example with custom resource //?simple_example8        System.out.println("--- Simple Resource ---");
    output=== Basic Try-with-Resources ===
    --- Simple Resource ---
  2. this.name ← myResource

    pass 1 of 4
    74public SimpleResource(String namemyResource) { //?constructor75    this.name→ myResource = namemyResource; //?set_name76    System.out.println("  [" + namemyResource + "] Resource opened"); //?print_opened77}
    output  [myResource] Resource opened
    All 4 passes — pass 1 is the card above
    passnametriggerErrorethis.nameresource
    1myResourcemyResource⟨SimpleResource A⟩
    2errorResourcetruejava.lang.RuntimeException: Something went wrong!errorResource⟨SimpleResource B⟩
    3finallyResourcefinallyResource⟨SimpleResource C⟩
    4oldStyleoldStyle⟨SimpleResource D⟩
  3. try (SimpleResource resource = new SimpleResource("myResource"))

    10try (SimpleResource resource⟨SimpleResource A⟩ = new SimpleResource("myResource")) { //?try_simple11    resource.doWork(); //?do_work12    System.out.println("Work completed"); //?work_completed
  4. public void doWork()

    pass 1 of 4
    10        try (SimpleResource resource = new SimpleResource("myResource")) { //?try_simple11            resource.doWork(); //?do_work12            System.out.println("Work completed"); //?work_completed13        } // close() called automatically here1415        System.out.println("After try block\n"); //?after_try1617        // With catch block //?with_catch18        System.out.println("--- With Catch Block ---");1920        boolean triggerError = true;  //@triggerError=true, false21        try (SimpleResource resource = new SimpleResource("errorResource")) { //?try_catch_example22            resource.doWork(); //?do_work_catch23            if (triggerError) { //?check_trigger_error24                resource.causeError(); //?cause_error25            }26        } catch (RuntimeException e) { //?catch_block27            System.out.println("Caught: " + e.getMessage()); //?print_caught28        }2930        System.out.println("Resource was still closed!\n"); //?still_closed3132        // With finally block //?with_finally33        System.out.println("--- With Finally Block ---");3435        try (SimpleResource resource = new SimpleResource("finallyResource")) { //?try_finally36            resource.doWork(); //?do_work_finally37        } finally { //?finally_block38            System.out.println("Finally block runs AFTER close()"); //?finally_message39        }4041        // Comparison with old style //?comparison42        System.out.println("\n--- Old Style (Don't Do This) ---");43        oldStyleExample(); //?call_old_style4445        System.out.println("\n=== Key Points ===");46        System.out.println("""47            1. Resource declared in try() parentheses48            2. Must implement AutoCloseable49            3. Automatically closed when try block exits50            4. Closed even if exception occurs51            5. catch and finally blocks are optional52            6. close() called BEFORE finally block53            """);54    }5556    static void oldStyleExample() { //?old_style_method57        SimpleResource resource = null; //?init_null58        try { //?old_try59            resource = new SimpleResource("oldStyle"); //?create_old60            resource.doWork(); //?work_old61        } finally { //?old_finally62            if (resource != null) { //?null_check63                resource.close(); //?manual_close64            }65        }66    }67}6869// Simple AutoCloseable resource //?simple_resource_class70class SimpleResource implements AutoCloseable { //?simple_resource_def71    private final String name; //?name_field72    private boolean closed = false; //?closed_field7374    public SimpleResource(String name) { //?constructor75        this.name = name; //?set_name76        System.out.println("  [" + name + "] Resource opened"); //?print_opened77    }7879    public void doWork() { //?do_work_method80        if (closed) throw new IllegalStateException("Resource is closed"); //?check_closed81        System.out.println("  [" + namemyResource + "] Doing work..."); //?print_working82    }
    output  [myResource] Doing work...
    Work completed
    All 4 passes — pass 1 is the card above
    passnameresourcetriggerErrore
    1myResource⟨SimpleResource B⟩
    2errorResourcetruejava.lang.RuntimeException: Something went wrong!
    3finallyResource
    4oldStyle⟨SimpleResource D⟩
  5. @Override //?override_close public void close()

    pass 1 of 4
    88@Override //?override_close89public void close() { //?close_method90    if (!closed) { //?if_not_closed
    All 4 passes — pass 1 is the card above
    passresourcetriggerErrore
    1⟨SimpleResource B⟩true
    2java.lang.RuntimeException: Something went wrong!
    3
    4
  6. closed ← true, triggerError ← true

    pass 1 of 4
    15        System.out.println("After try block\n"); //?after_try1617        // With catch block //?with_catch18        System.out.println("--- With Catch Block ---");1920        boolean triggerError→ true = true;  //@triggerError=true, false21        try (SimpleResource resource = new SimpleResource("errorResource")) { //?try_catch_example22            resource.doWork(); //?do_work_catch23            if (triggerError) { //?check_trigger_error24                resource.causeError(); //?cause_error25            }26        } catch (RuntimeException e) { //?catch_block27            System.out.println("Caught: " + e.getMessage()); //?print_caught28        }2930        System.out.println("Resource was still closed!\n"); //?still_closed3132        // With finally block //?with_finally33        System.out.println("--- With Finally Block ---");3435        try (SimpleResource resource = new SimpleResource("finallyResource")) { //?try_finally36            resource.doWork(); //?do_work_finally37        } finally { //?finally_block38            System.out.println("Finally block runs AFTER close()"); //?finally_message39        }4041        // Comparison with old style //?comparison42        System.out.println("\n--- Old Style (Don't Do This) ---");43        oldStyleExample(); //?call_old_style4445        System.out.println("\n=== Key Points ===");46        System.out.println("""47            1. Resource declared in try() parentheses48            2. Must implement AutoCloseable49            3. Automatically closed when try block exits50            4. Closed even if exception occurs51            5. catch and finally blocks are optional52            6. close() called BEFORE finally block53            """);54    }5556    static void oldStyleExample() { //?old_style_method57        SimpleResource resource = null; //?init_null58        try { //?old_try59            resource = new SimpleResource("oldStyle"); //?create_old60            resource.doWork(); //?work_old61        } finally { //?old_finally62            if (resource != null) { //?null_check63                resource.close(); //?manual_close64            }65        }66    }67}6869// Simple AutoCloseable resource //?simple_resource_class70class SimpleResource implements AutoCloseable { //?simple_resource_def71    private final String name; //?name_field72    private boolean closed = false; //?closed_field7374    public SimpleResource(String name) { //?constructor75        this.name = name; //?set_name76        System.out.println("  [" + name + "] Resource opened"); //?print_opened77    }7879    public void doWork() { //?do_work_method80        if (closed) throw new IllegalStateException("Resource is closed"); //?check_closed81        System.out.println("  [" + name + "] Doing work..."); //?print_working82    }8384    public void causeError() { //?cause_error_method85        throw new RuntimeException("Something went wrong!"); //?throw_error86    }8788    @Override //?override_close89    public void close() { //?close_method90        if (!closedfalse) { //?if_not_closed91            closed→ true = true; //?set_closed92            System.out.println("  [" + namemyResource + "] Resource closed"); //?print_closed93        }
    output  [myResource] Resource closed
    After try block
    --- With Catch Block ---
    All 4 passes — pass 1 is the card above
    passnameresourceeclosedtriggerError
    1myResource⟨SimpleResource B⟩false truetrue
    2errorResourcejava.lang.RuntimeException: Something went wrong!false true
    3finallyResourcefalse true
    4oldStylefalse true
  7. try (SimpleResource resource = new SimpleResource("errorResource"))

    20boolean triggerError = true;  //@triggerError=true, false21try (SimpleResource resource⟨SimpleResource B⟩ = new SimpleResource("errorResource")) { //?try_catch_example22    resource.doWork(); //?do_work_catch23    if (triggerError) { //?check_trigger_error
  8. if (triggerError)

    22resource.doWork(); //?do_work_catch23if (triggerErrortrue) { //?check_trigger_error24    resource.causeError(); //?cause_error25}
  9. catch (RuntimeException e)

    25    }26} catch (RuntimeException ejava.lang.RuntimeException: Something went wrong!) { //?catch_block27    System.out.println("Caught: " + e.getMessage()); //?print_caught28}
    outputCaught: Something went wrong!
  10. System.out.println("Resource was still closed! "); //?still_closed

    30System.out.println("Resource was still closed!\n"); //?still_closed3132// With finally block //?with_finally33System.out.println("--- With Finally Block ---");
    outputResource was still closed!
    --- With Finally Block ---
  11. try (SimpleResource resource = new SimpleResource("finallyResource"))

    35try (SimpleResource resource⟨SimpleResource C⟩ = new SimpleResource("finallyResource")) { //?try_finally36    resource.doWork(); //?do_work_finally37} finally { //?finally_block
  12. 36    resource.doWork(); //?do_work_finally37} finally { //?finally_block38    System.out.println("Finally block runs AFTER close()"); //?finally_message39}
    outputFinally block runs AFTER close()
  13. System.out.println(" --- Old Style (Don't Do This) ---");

    41// Comparison with old style //?comparison42System.out.println("\n--- Old Style (Don't Do This) ---");43oldStyleExample(); //?call_old_style
    output
    --- Old Style (Don't Do This) ---
  14. resource ← null

    56static void oldStyleExample() { //?old_style_method57    SimpleResource resource→ null = null; //?init_null58    try { //?old_try
  15. if (resource != null)

    61} finally { //?old_finally62    if (resource⟨SimpleResource D⟩ != null) { //?null_check63        resource.close(); //?manual_close64    }
  1. public static void main(String[] args)

    3public class BasicSyntax {4    public static void main(String[] args) {5        System.out.println("=== Basic Try-with-Resources ===\n");67        // Simple example with custom resource8        System.out.println("--- Simple Resource ---");
    output=== Basic Try-with-Resources ===
    --- Simple Resource ---
  2. this.name ← myResource

    pass 1 of 4
    74public SimpleResource(String namemyResource) {75    this.name→ myResource = namemyResource;76    System.out.println("  [" + namemyResource + "] Resource opened");77}
    output  [myResource] Resource opened
    All 4 passes — pass 1 is the card above
    passnamethis.nameresource
    1myResourcemyResource⟨SimpleResource A⟩
    2errorResourceerrorResource⟨SimpleResource B⟩
    3finallyResourcefinallyResource⟨SimpleResource C⟩
    4oldStyleoldStyle⟨SimpleResource D⟩
  3. try (SimpleResource resource = new SimpleResource("myResource"))

    10try (SimpleResource resource⟨SimpleResource A⟩ = new SimpleResource("myResource")) {11    resource.doWork();12    System.out.println("Work completed");
  4. public void doWork()

    pass 1 of 4
    10        try (SimpleResource resource = new SimpleResource("myResource")) {11            resource.doWork();12            System.out.println("Work completed");13        } // close() called automatically here1415        System.out.println("After try block\n");1617        // With catch block18        System.out.println("--- With Catch Block ---");1920        boolean triggerError = false;21        try (SimpleResource resource = new SimpleResource("errorResource")) {22            resource.doWork();23            if (triggerError) {24                resource.causeError();25            }26        } catch (RuntimeException e) {27            System.out.println("Caught: " + e.getMessage());28        }2930        System.out.println("Resource was still closed!\n");3132        // With finally block33        System.out.println("--- With Finally Block ---");3435        try (SimpleResource resource = new SimpleResource("finallyResource")) {36            resource.doWork();37        } finally {38            System.out.println("Finally block runs AFTER close()");39        }4041        // Comparison with old style42        System.out.println("\n--- Old Style (Don't Do This) ---");43        oldStyleExample();4445        System.out.println("\n=== Key Points ===");46        System.out.println("""47            1. Resource declared in try() parentheses48            2. Must implement AutoCloseable49            3. Automatically closed when try block exits50            4. Closed even if exception occurs51            5. catch and finally blocks are optional52            6. close() called BEFORE finally block53            """);54    }5556    static void oldStyleExample() {57        SimpleResource resource = null;58        try {59            resource = new SimpleResource("oldStyle");60            resource.doWork();61        } finally {62            if (resource != null) {63                resource.close();64            }65        }66    }67}6869// Simple AutoCloseable resource70class SimpleResource implements AutoCloseable {71    private final String name;72    private boolean closed = false;7374    public SimpleResource(String name) {75        this.name = name;76        System.out.println("  [" + name + "] Resource opened");77    }7879    public void doWork() {80        if (closed) throw new IllegalStateException("Resource is closed");81        System.out.println("  [" + namemyResource + "] Doing work...");82    }
    output  [myResource] Doing work...
    Work completed
    All 4 passes — pass 1 is the card above
    passnameresource
    1myResource⟨SimpleResource B⟩
    2errorResource⟨SimpleResource C⟩
    3finallyResource
    4oldStyle⟨SimpleResource D⟩
  5. @Override public void close()

    pass 1 of 4
    88@Override89public void close() {90    if (!closed) {
    All 4 passes — pass 1 is the card above
    passresource
    1⟨SimpleResource B⟩
    2⟨SimpleResource C⟩
    3
    4
  6. closed ← true, triggerError ← false

    pass 1 of 4
    15        System.out.println("After try block\n");1617        // With catch block18        System.out.println("--- With Catch Block ---");1920        boolean triggerError→ false = false;21        try (SimpleResource resource = new SimpleResource("errorResource")) {22            resource.doWork();23            if (triggerError) {24                resource.causeError();25            }26        } catch (RuntimeException e) {27            System.out.println("Caught: " + e.getMessage());28        }2930        System.out.println("Resource was still closed!\n");3132        // With finally block33        System.out.println("--- With Finally Block ---");3435        try (SimpleResource resource = new SimpleResource("finallyResource")) {36            resource.doWork();37        } finally {38            System.out.println("Finally block runs AFTER close()");39        }4041        // Comparison with old style42        System.out.println("\n--- Old Style (Don't Do This) ---");43        oldStyleExample();4445        System.out.println("\n=== Key Points ===");46        System.out.println("""47            1. Resource declared in try() parentheses48            2. Must implement AutoCloseable49            3. Automatically closed when try block exits50            4. Closed even if exception occurs51            5. catch and finally blocks are optional52            6. close() called BEFORE finally block53            """);54    }5556    static void oldStyleExample() {57        SimpleResource resource = null;58        try {59            resource = new SimpleResource("oldStyle");60            resource.doWork();61        } finally {62            if (resource != null) {63                resource.close();64            }65        }66    }67}6869// Simple AutoCloseable resource70class SimpleResource implements AutoCloseable {71    private final String name;72    private boolean closed = false;7374    public SimpleResource(String name) {75        this.name = name;76        System.out.println("  [" + name + "] Resource opened");77    }7879    public void doWork() {80        if (closed) throw new IllegalStateException("Resource is closed");81        System.out.println("  [" + name + "] Doing work...");82    }8384    public void causeError() {85        throw new RuntimeException("Something went wrong!");86    }8788    @Override89    public void close() {90        if (!closedfalse) {91            closed→ true = true;92            System.out.println("  [" + namemyResource + "] Resource closed");93        }
    output  [myResource] Resource closed
    After try block
    --- With Catch Block ---
    All 4 passes — pass 1 is the card above
    passnameresourceclosedtriggerError
    1myResource⟨SimpleResource B⟩false truefalse
    2errorResource⟨SimpleResource C⟩false true
    3finallyResourcefalse true
    4oldStylefalse true
  7. try (SimpleResource resource = new SimpleResource("errorResource"))

    20boolean triggerError = false;21try (SimpleResource resource⟨SimpleResource B⟩ = new SimpleResource("errorResource")) {22    resource.doWork();23    if (triggerError) {
  8. try (SimpleResource resource = new SimpleResource("finallyResource"))

    35try (SimpleResource resource⟨SimpleResource C⟩ = new SimpleResource("finallyResource")) {36    resource.doWork();37} finally {
  9. 36    resource.doWork();37} finally {38    System.out.println("Finally block runs AFTER close()");39}
    outputFinally block runs AFTER close()
  10. System.out.println(" --- Old Style (Don't Do This) ---");

    41// Comparison with old style42System.out.println("\n--- Old Style (Don't Do This) ---");43oldStyleExample();
    output
    --- Old Style (Don't Do This) ---
  11. resource ← null

    56static void oldStyleExample() {57    SimpleResource resource→ null = null;58    try {
  12. if (resource != null)

    61} finally {62    if (resource⟨SimpleResource D⟩ != null) {63        resource.close();64    }

try (Resource r = new Resource()) { } - automatically closed after block.

try-with-resources Automatic resource management. Resource closed when block exits.

Multiple resources

Manage several resources at once.

MultipleResources.java
Replay: real traced execution (multi-file project)
// Managing Multiple Resources

public class MultipleResources {
    public static void main(String[] args) {
        System.out.println("=== Multiple Resources ===\n");

        // Multiple resources - closed in reverse order
        System.out.println("--- Multiple Resources (Reverse Close Order) ---");

        try (
            Resource r1 = new Resource("first");
            Resource r2 = new Resource("second");
            Resource r3 = new Resource("third")
        ) {
            System.out.println("Using all resources...");
            r1.use();
            r2.use();
            r3.use();
        }

        System.out.println();

        // Chained resources
        System.out.println("--- Chained Resources ---");

        try (
            OuterResource outer = new OuterResource("outer");
            InnerResource inner = new InnerResource("inner", outer)
        ) {
            inner.process();
        }

        System.out.println();

        // One resource fails to open
        System.out.println("--- When Opening Fails ---");

        try (
            Resource r1 = new Resource("good1");
            Resource r2 = new FailingResource("failing");
            Resource r3 = new Resource("good2")
        ) {
            System.out.println("This won't execute");
        } catch (RuntimeException e) {
            System.out.println("Caught: " + e.getMessage());
        }

        System.out.println("\nNotice: Only successfully opened resources are closed.");

        System.out.println();

        // Exception during use
        System.out.println("--- Exception During Use ---");

        try (
            Resource r1 = new Resource("A");
            Resource r2 = new Resource("B");
            Resource r3 = new Resource("C")
        ) {
            r1.use();
            throw new RuntimeException("Error during processing");
        } catch (RuntimeException e) {
            System.out.println("Caught: " + e.getMessage());
        }

        System.out.println("All resources were closed despite the exception.");

        System.out.println("\n=== Key Points ===");
        System.out.println("""
            1. Declare multiple resources separated by semicolons
            2. Resources closed in REVERSE order (LIFO)
            3. If opening fails, previously opened resources are closed
            4. All resources closed even if exception in try body
            5. Useful for dependent resources (e.g., BufferedReader wraps FileReader)
            """);
    }
}

// Basic resource
class Resource implements AutoCloseable {
    protected final String name;

    public Resource(String name) {
        this.name = name;
        System.out.println("  → Opening: " + name);
    }

    public void use() {
        System.out.println("    Using: " + name);
    }

    @Override
    public void close() {
        System.out.println("  ← Closing: " + name);
    }
}

// Resource that fails during construction
class FailingResource extends Resource {
    public FailingResource(String name) {
        super(name);
        throw new RuntimeException("Failed to open: " + name);
    }
}

// Outer resource
class OuterResource implements AutoCloseable {
    private final String name;

    public OuterResource(String name) {
        this.name = name;
        System.out.println("  → Opening outer: " + name);
    }

    public String getData() {
        return "data from " + name;
    }

    @Override
    public void close() {
        System.out.println("  ← Closing outer: " + name);
    }
}

// Inner resource that depends on outer
class InnerResource implements AutoCloseable {
    private final String name;
    private final OuterResource outer;

    public InnerResource(String name, OuterResource outer) {
        this.name = name;
        this.outer = outer;
        System.out.println("  → Opening inner: " + name + " (wraps " + outer.getData() + ")");
    }

    public void process() {
        System.out.println("    Processing with " + outer.getData());
    }

    @Override
    public void close() {
        System.out.println("  ← Closing inner: " + name);
    }
}

//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
  1. public static void main(String[] args)

    3public class MultipleResources {4    public static void main(String[] args) {5        System.out.println("=== Multiple Resources ===\n");67        // Multiple resources - closed in reverse order //?multiple_basic8        System.out.println("--- Multiple Resources (Reverse Close Order) ---");
    output=== Multiple Resources ===
    --- Multiple Resources (Reverse Close Order) ---
  2. this.name ← first

    pass 1 of 8
    83public Resource(String namefirst) { //?resource_constructor84    this.name→ first = namefirst;85    System.out.println("  → Opening: " + namefirst); //?print_opening86}
    output  → Opening: first
    All 8 passes — pass 1 is the card above
    passnamer1r2r3outerethis.namethis.outer
    1firstfirst
    2secondsecond
    3third⟨Resource A⟩⟨Resource B⟩⟨Resource C⟩⟨OuterResource D⟩third⟨OuterResource D⟩
    4good1good1
    5failingjava.lang.RuntimeException: Failed to open: failingfailing
    6AA
    7BB
    8C⟨Resource E⟩⟨Resource F⟩⟨Resource G⟩java.lang.RuntimeException: Error during processingC
  3. try ( //?try_multiple Resource r1 = new Resource("first");…

    10try ( //?try_multiple11    Resource r1⟨Resource A⟩ = new Resource("first");   //?resource112    Resource r2⟨Resource B⟩ = new Resource("second");  //?resource213    Resource r3⟨Resource C⟩ = new Resource("third")    //?resource314) { //?multiple_body15    System.out.println("Using all resources..."); //?using_all16    r1.use(); //?use_r117    r2.use(); //?use_r2
    outputUsing all resources...
  4. public void use()

    pass 1 of 4
    15            System.out.println("Using all resources..."); //?using_all16            r1.use(); //?use_r117            r2.use(); //?use_r218            r3.use(); //?use_r319        }2021        System.out.println(); //?newline2223        // Chained resources //?chained24        System.out.println("--- Chained Resources ---");2526        try ( //?try_chained27            OuterResource outer = new OuterResource("outer"); //?outer28            InnerResource inner = new InnerResource("inner", outer) //?inner29        ) {30            inner.process(); //?process_inner31        }3233        System.out.println(); //?newline23435        // One resource fails to open //?fail_to_open36        System.out.println("--- When Opening Fails ---");3738        try ( //?try_fail_open39            Resource r1 = new Resource("good1"); //?good140            Resource r2 = new FailingResource("failing"); //?failing41            Resource r3 = new Resource("good2") //?good2_never42        ) {43            System.out.println("This won't execute"); //?wont_execute44        } catch (RuntimeException e) { //?catch_fail_open45            System.out.println("Caught: " + e.getMessage()); //?print_fail_open46        }4748        System.out.println("\nNotice: Only successfully opened resources are closed."); //?notice4950        System.out.println(); //?newline35152        // Exception during use //?exception_during_use53        System.out.println("--- Exception During Use ---");5455        try ( //?try_exception_use56            Resource r1 = new Resource("A"); //?res_a57            Resource r2 = new Resource("B"); //?res_b58            Resource r3 = new Resource("C")  //?res_c59        ) {60            r1.use(); //?use_a61            throw new RuntimeException("Error during processing"); //?throw_during62        } catch (RuntimeException e) { //?catch_during63            System.out.println("Caught: " + e.getMessage()); //?print_during64        }6566        System.out.println("All resources were closed despite the exception."); //?all_closed6768        System.out.println("\n=== Key Points ===");69        System.out.println("""70            1. Declare multiple resources separated by semicolons71            2. Resources closed in REVERSE order (LIFO)72            3. If opening fails, previously opened resources are closed73            4. All resources closed even if exception in try body74            5. Useful for dependent resources (e.g., BufferedReader wraps FileReader)75            """);76    }77}7879// Basic resource //?resource_class80class Resource implements AutoCloseable { //?resource_def81    protected final String name; //?resource_name8283    public Resource(String name) { //?resource_constructor84        this.name = name;85        System.out.println("  → Opening: " + name); //?print_opening86    }8788    public void use() { //?use_method89        System.out.println("    Using: " + namefirst); //?print_using90    }
    output    Using: first
    All 4 passes — pass 1 is the card above
    passnameouterethis.namethis.outer
    1first
    2second
    3third⟨OuterResource D⟩outer⟨OuterResource D⟩
    4Ajava.lang.RuntimeException: Error during processing
  5. @Override public void close()

    pass 1 of 7
    92@Override93public void close() { //?close_resource94    System.out.println("  ← Closing: " + namethird); //?print_closing95}
    output  ← Closing: third
    All 7 passes — pass 1 is the card above
    passnameouterethis.namethis.outer
    1third
    2second
    3first⟨OuterResource D⟩outer⟨OuterResource D⟩
    4good1java.lang.RuntimeException: Failed to open: failing
    5C
    6B
    7Ajava.lang.RuntimeException: Error during processing
  6. this.name ← outer

    110public OuterResource(String nameouter) { //?outer_constructor111    this.name→ outer = nameouter;112    System.out.println("  → Opening outer: " + nameouter); //?print_outer_open113}
    output  → Opening outer: outer
  7. this.name ← inner, this.outer ← ⟨OuterResource D⟩

    130public InnerResource(String nameinner, OuterResource outer⟨OuterResource D⟩) { //?inner_constructor131    this.name→ inner = nameinner;132    this.outer→ ⟨OuterResource D⟩ = outer⟨OuterResource D⟩;133    System.out.println("  → Opening inner: " + nameinner + " (wraps " + outer.getData() + ")"); //?print_inner_open134}
  8. public String getData()

    pass 1 of 2
    115public String getData() { //?get_data116    return "data from " + nameouter; //?return_data117}
  9. System.out.println(" → Opening inner: " + name + " (wraps " + outer.g…

    132    this.outer = outer;133    System.out.println("  → Opening inner: " + nameinner + " (wraps " + outer.getData() + ")"); //?print_inner_open134}
    output  → Opening inner: inner (wraps data from outer)
  10. try ( //?try_chained OuterResource outer = new OuterResour…

    26try ( //?try_chained27    OuterResource outer⟨OuterResource D⟩ = new OuterResource("outer"); //?outer28    InnerResource inner⟨InnerResource H⟩ = new InnerResource("inner", outer) //?inner29) {30    inner.process(); //?process_inner31}
  11. public String getData()

    pass 2 of 2
    115public String getData() { //?get_data116    return "data from " + nameouter; //?return_data117}
  12. System.out.println(" Processing with " + outer.getData()); //?print…

    29        ) {30            inner.process(); //?process_inner31        }3233        System.out.println(); //?newline23435        // One resource fails to open //?fail_to_open36        System.out.println("--- When Opening Fails ---");3738        try ( //?try_fail_open39            Resource r1 = new Resource("good1"); //?good140            Resource r2 = new FailingResource("failing"); //?failing41            Resource r3 = new Resource("good2") //?good2_never42        ) {43            System.out.println("This won't execute"); //?wont_execute44        } catch (RuntimeException e) { //?catch_fail_open45            System.out.println("Caught: " + e.getMessage()); //?print_fail_open46        }4748        System.out.println("\nNotice: Only successfully opened resources are closed."); //?notice4950        System.out.println(); //?newline35152        // Exception during use //?exception_during_use53        System.out.println("--- Exception During Use ---");5455        try ( //?try_exception_use56            Resource r1 = new Resource("A"); //?res_a57            Resource r2 = new Resource("B"); //?res_b58            Resource r3 = new Resource("C")  //?res_c59        ) {60            r1.use(); //?use_a61            throw new RuntimeException("Error during processing"); //?throw_during62        } catch (RuntimeException e) { //?catch_during63            System.out.println("Caught: " + e.getMessage()); //?print_during64        }6566        System.out.println("All resources were closed despite the exception."); //?all_closed6768        System.out.println("\n=== Key Points ===");69        System.out.println("""70            1. Declare multiple resources separated by semicolons71            2. Resources closed in REVERSE order (LIFO)72            3. If opening fails, previously opened resources are closed73            4. All resources closed even if exception in try body74            5. Useful for dependent resources (e.g., BufferedReader wraps FileReader)75            """);76    }77}7879// Basic resource //?resource_class80class Resource implements AutoCloseable { //?resource_def81    protected final String name; //?resource_name8283    public Resource(String name) { //?resource_constructor84        this.name = name;85        System.out.println("  → Opening: " + name); //?print_opening86    }8788    public void use() { //?use_method89        System.out.println("    Using: " + name); //?print_using90    }9192    @Override93    public void close() { //?close_resource94        System.out.println("  ← Closing: " + name); //?print_closing95    }96}9798// Resource that fails during construction //?failing_resource_class99class FailingResource extends Resource { //?failing_resource_def100    public FailingResource(String name) { //?failing_constructor101        super(name); //?super_call102        throw new RuntimeException("Failed to open: " + name); //?throw_fail103    }104}105106// Outer resource //?outer_resource_class107class OuterResource implements AutoCloseable { //?outer_def108    private final String name; //?outer_name109110    public OuterResource(String name) { //?outer_constructor111        this.name = name;112        System.out.println("  → Opening outer: " + name); //?print_outer_open113    }114115    public String getData() { //?get_data116        return "data from " + name; //?return_data117    }118119    @Override120    public void close() { //?close_outer121        System.out.println("  ← Closing outer: " + name); //?print_outer_close122    }123}124125// Inner resource that depends on outer //?inner_resource_class126class InnerResource implements AutoCloseable { //?inner_def127    private final String name; //?inner_name128    private final OuterResource outer; //?outer_ref129130    public InnerResource(String name, OuterResource outer) { //?inner_constructor131        this.name = name;132        this.outer = outer;133        System.out.println("  → Opening inner: " + name + " (wraps " + outer.getData() + ")"); //?print_inner_open134    }135136    public void process() { //?process_method137        System.out.println("    Processing with " + outer.getData()); //?print_process138    }
    output    Processing with data from outer
  13. @Override public void close()

    140@Override141public void close() { //?close_inner142    System.out.println("  ← Closing inner: " + nameinner); //?print_inner_close143}
    output  ← Closing inner: inner
  14. @Override public void close()

    33        System.out.println(); //?newline23435        // One resource fails to open //?fail_to_open36        System.out.println("--- When Opening Fails ---");3738        try ( //?try_fail_open39            Resource r1 = new Resource("good1"); //?good140            Resource r2 = new FailingResource("failing"); //?failing41            Resource r3 = new Resource("good2") //?good2_never42        ) {43            System.out.println("This won't execute"); //?wont_execute44        } catch (RuntimeException e) { //?catch_fail_open45            System.out.println("Caught: " + e.getMessage()); //?print_fail_open46        }4748        System.out.println("\nNotice: Only successfully opened resources are closed."); //?notice4950        System.out.println(); //?newline35152        // Exception during use //?exception_during_use53        System.out.println("--- Exception During Use ---");5455        try ( //?try_exception_use56            Resource r1 = new Resource("A"); //?res_a57            Resource r2 = new Resource("B"); //?res_b58            Resource r3 = new Resource("C")  //?res_c59        ) {60            r1.use(); //?use_a61            throw new RuntimeException("Error during processing"); //?throw_during62        } catch (RuntimeException e) { //?catch_during63            System.out.println("Caught: " + e.getMessage()); //?print_during64        }6566        System.out.println("All resources were closed despite the exception."); //?all_closed6768        System.out.println("\n=== Key Points ===");69        System.out.println("""70            1. Declare multiple resources separated by semicolons71            2. Resources closed in REVERSE order (LIFO)72            3. If opening fails, previously opened resources are closed73            4. All resources closed even if exception in try body74            5. Useful for dependent resources (e.g., BufferedReader wraps FileReader)75            """);76    }77}7879// Basic resource //?resource_class80class Resource implements AutoCloseable { //?resource_def81    protected final String name; //?resource_name8283    public Resource(String name) { //?resource_constructor84        this.name = name;85        System.out.println("  → Opening: " + name); //?print_opening86    }8788    public void use() { //?use_method89        System.out.println("    Using: " + name); //?print_using90    }9192    @Override93    public void close() { //?close_resource94        System.out.println("  ← Closing: " + name); //?print_closing95    }96}9798// Resource that fails during construction //?failing_resource_class99class FailingResource extends Resource { //?failing_resource_def100    public FailingResource(String name) { //?failing_constructor101        super(name); //?super_call102        throw new RuntimeException("Failed to open: " + name); //?throw_fail103    }104}105106// Outer resource //?outer_resource_class107class OuterResource implements AutoCloseable { //?outer_def108    private final String name; //?outer_name109110    public OuterResource(String name) { //?outer_constructor111        this.name = name;112        System.out.println("  → Opening outer: " + name); //?print_outer_open113    }114115    public String getData() { //?get_data116        return "data from " + name; //?return_data117    }118119    @Override120    public void close() { //?close_outer121        System.out.println("  ← Closing outer: " + nameouter); //?print_outer_close122    }
    output  ← Closing outer: outer
    --- When Opening Fails ---
  15. public FailingResource(String name)

    99class FailingResource extends Resource { //?failing_resource_def100    public FailingResource(String namefailing) { //?failing_constructor101        super(name); //?super_call102        throw new RuntimeException("Failed to open: " + name); //?throw_fail103    }
  16. catch (RuntimeException e)

    43    System.out.println("This won't execute"); //?wont_execute44} catch (RuntimeException ejava.lang.RuntimeException: Failed to open: failing) { //?catch_fail_open45    System.out.println("Caught: " + e.getMessage()); //?print_fail_open46}
    outputCaught: Failed to open: failing
  17. System.out.println(" Notice: Only successfully opened resources are cl…

    48System.out.println("\nNotice: Only successfully opened resources are closed."); //?notice4950System.out.println(); //?newline35152// Exception during use //?exception_during_use53System.out.println("--- Exception During Use ---");
    output
    Notice: Only successfully opened resources are closed.
    --- Exception During Use ---
  18. try ( //?try_exception_use Resource r1 = new Resource("A")…

    55try ( //?try_exception_use56    Resource r1⟨Resource E⟩ = new Resource("A"); //?res_a57    Resource r2⟨Resource F⟩ = new Resource("B"); //?res_b58    Resource r3⟨Resource G⟩ = new Resource("C")  //?res_c59) {60    r1.use(); //?use_a61    throw new RuntimeException("Error during processing"); //?throw_during
  19. catch (RuntimeException e)

    61    throw new RuntimeException("Error during processing"); //?throw_during62} catch (RuntimeException ejava.lang.RuntimeException: Error during processing) { //?catch_during63    System.out.println("Caught: " + e.getMessage()); //?print_during64}
    outputCaught: Error during processing
  20. System.out.println("All resources were closed despite the exception.")…

    66    System.out.println("All resources were closed despite the exception."); //?all_closed6768    System.out.println("\n=== Key Points ===");69    System.out.println("""70        1. Declare multiple resources separated by semicolons71        2. Resources closed in REVERSE order (LIFO)72        3. If opening fails, previously opened resources are closed73        4. All resources closed even if exception in try body74        5. Useful for dependent resources (e.g., BufferedReader wraps FileReader)75        """);76}
    outputAll resources were closed despite the exception.
    
    === Key Points ===
    1. Declare multiple resources separated by semicolons
    2. Resources closed in REVERSE order (LIFO)
    3. If opening fails, previously opened resources are closed
    4. All resources closed even if exception in try body
    5. Useful for dependent resources (e.g., BufferedReader wraps FileReader)

Resources closed in reverse order of declaration. All get closed.

Custom AutoCloseable

Make your own resources work with try-with-resources.

CustomAutocloseable.java
Replay: real traced execution (multi-file project)
// Creating Custom AutoCloseable Classes

public class CustomAutocloseable {
    public static void main(String[] args) {
        System.out.println("=== Custom AutoCloseable Classes ===\n");

        // Basic custom resource
        System.out.println("--- Basic Custom Resource ---");

        try (Timer timer = new Timer("operation")) {
            timer.simulateWork(100);
            System.out.println("  Operation completed");
        }

        // Resource with state
        System.out.println("\n--- Stateful Resource ---");

        try (Counter counter = new Counter()) {
            counter.increment();
            counter.increment();
            counter.increment();
            System.out.println("  Count: " + counter.getCount());
        }

        // Resource that can fail on close
        System.out.println("\n--- Resource That May Fail on Close ---");

        try (SafeResource resource = new SafeResource()) {
            resource.process();
        }

        // Idempotent close
        System.out.println("\n--- Idempotent Close ---");

        try (IdempotentResource resource = new IdempotentResource()) {
            resource.use();
            resource.close();
            resource.close();
            // Will be called again automatically
        }

        // Resource with cleanup action
        System.out.println("\n--- Resource with Cleanup Callback ---");

        try (CallbackResource resource = new CallbackResource(
                () -> System.out.println("  [Cleanup] Resources freed!"))) {
            resource.process();
        }

        System.out.println("\n=== Key Points ===");
        System.out.println("""
            1. Implement AutoCloseable interface
            2. close() should be idempotent (safe to call multiple times)
            3. Don't throw exceptions in close() if possible
            4. Track state to prevent use after close
            5. Consider what cleanup is actually needed
            """);
    }
}

// Timer resource - measures elapsed time
class Timer implements AutoCloseable {
    private final String operationName;
    private long elapsedMs = 0;

    public Timer(String operationName) {
        this.operationName = operationName;
        System.out.println("  [Timer] Started: " + operationName);
    }

    public void simulateWork(long millis) {
        elapsedMs += millis;
    }

    @Override
    public void close() {
        System.out.println("  [Timer] " + operationName + " took " + elapsedMs + "ms");
    }
}

// Counter resource - tracks count
class Counter implements AutoCloseable {
    private int count = 0;
    private boolean closed = false;

    public void increment() {
        checkNotClosed();
        count++;
    }

    public int getCount() {
        checkNotClosed();
        return count;
    }

    private void checkNotClosed() {
        if (closed) {
            throw new IllegalStateException("Counter is closed");
        }
    }

    @Override
    public void close() {
        if (!closed) {
            System.out.println("  [Counter] Final count: " + count);
            closed = true;
        }
    }
}

// Resource that handles close errors gracefully
class SafeResource implements AutoCloseable {

    public void process() {
        System.out.println("  [SafeResource] Processing...");
    }

    @Override
    public void close() {
        System.out.println("  [SafeResource] Closing...");
        try {
            // Simulate cleanup that might fail
            performCleanup();
        } catch (Exception e) {
            // Log but don't rethrow
            System.out.println("  [SafeResource] Cleanup warning: " + e.getMessage());
        }
        System.out.println("  [SafeResource] Closed (even if cleanup had issues)");
    }

    private void performCleanup() {
        // In real code, this might fail
        System.out.println("  [SafeResource] Cleanup succeeded");
    }
}

// Resource with idempotent close
class IdempotentResource implements AutoCloseable {
    private boolean closed = false;
    private int closeCallCount = 0;

    public void use() {
        if (closed) throw new IllegalStateException("Already closed");
        System.out.println("  [Idempotent] Using resource");
    }

    @Override
    public void close() {
        closeCallCount++;
        System.out.println("  [Idempotent] close() called (call #" + closeCallCount + ")");

        if (!closed) {
            closed = true;
            System.out.println("  [Idempotent] Actually closing resources");
        } else {
            System.out.println("  [Idempotent] Already closed, doing nothing");
        }
    }
}

// Resource with cleanup callback
class CallbackResource implements AutoCloseable {
    private final Runnable cleanupAction;

    public CallbackResource(Runnable cleanupAction) {
        this.cleanupAction = cleanupAction;
        System.out.println("  [Callback] Resource created");
    }

    public void process() {
        System.out.println("  [Callback] Processing...");
    }

    @Override
    public void close() {
        System.out.println("  [Callback] Closing...");
        cleanupAction.run();
    }
}

//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
  1. public static void main(String[] args)

    3public class CustomAutocloseable {4    public static void main(String[] args) {5        System.out.println("=== Custom AutoCloseable Classes ===\n");67        // Basic custom resource //?basic_custom8        System.out.println("--- Basic Custom Resource ---");
    output=== Custom AutoCloseable Classes ===
    --- Basic Custom Resource ---
  2. this.operationName ← operation

    66public Timer(String operationNameoperation) { //?timer_constructor67    this.operationName→ operation = operationNameoperation;68    System.out.println("  [Timer] Started: " + operationNameoperation); //?print_started69}
    output  [Timer] Started: operation
  3. try (Timer timer = new Timer("operation"))

    10try (Timer timer⟨Timer A⟩ = new Timer("operation")) { //?try_timer11    timer.simulateWork(100); //?simulate_work12    System.out.println("  Operation completed"); //?completed
  4. elapsedMs ← 100

    10        try (Timer timer = new Timer("operation")) { //?try_timer11            timer.simulateWork(100); //?simulate_work12            System.out.println("  Operation completed"); //?completed13        }1415        // Resource with state //?stateful16        System.out.println("\n--- Stateful Resource ---");1718        try (Counter counter = new Counter()) { //?try_counter19            counter.increment(); //?inc120            counter.increment(); //?inc221            counter.increment(); //?inc322            System.out.println("  Count: " + counter.getCount()); //?print_count23        }2425        // Resource that can fail on close //?fail_on_close26        System.out.println("\n--- Resource That May Fail on Close ---");2728        try (SafeResource resource = new SafeResource()) { //?try_safe29            resource.process(); //?process_safe30        }3132        // Idempotent close //?idempotent33        System.out.println("\n--- Idempotent Close ---");3435        try (IdempotentResource resource = new IdempotentResource()) { //?try_idempotent36            resource.use(); //?use_idempotent37            resource.close(); //?manual_close38            resource.close(); //?manual_close239            // Will be called again automatically //?auto_close_comment40        }4142        // Resource with cleanup action //?cleanup_action43        System.out.println("\n--- Resource with Cleanup Callback ---");4445        try (CallbackResource resource = new CallbackResource( //?try_callback46                () -> System.out.println("  [Cleanup] Resources freed!"))) { //?callback_lambda47            resource.process(); //?process_callback48        }4950        System.out.println("\n=== Key Points ===");51        System.out.println("""52            1. Implement AutoCloseable interface53            2. close() should be idempotent (safe to call multiple times)54            3. Don't throw exceptions in close() if possible55            4. Track state to prevent use after close56            5. Consider what cleanup is actually needed57            """);58    }59}6061// Timer resource - measures elapsed time //?timer_class62class Timer implements AutoCloseable { //?timer_def63    private final String operationName; //?operation_name64    private long elapsedMs = 0; //?elapsed_field6566    public Timer(String operationName) { //?timer_constructor67        this.operationName = operationName;68        System.out.println("  [Timer] Started: " + operationName); //?print_started69    }7071    public void simulateWork(long millis100) { //?simulate_work_method72        elapsedMs→ 100 += millis100; //?add_elapsed73    }
    output  Operation completed
  5. @Override public void close()

    15        // Resource with state //?stateful16        System.out.println("\n--- Stateful Resource ---");1718        try (Counter counter = new Counter()) { //?try_counter19            counter.increment(); //?inc120            counter.increment(); //?inc221            counter.increment(); //?inc322            System.out.println("  Count: " + counter.getCount()); //?print_count23        }2425        // Resource that can fail on close //?fail_on_close26        System.out.println("\n--- Resource That May Fail on Close ---");2728        try (SafeResource resource = new SafeResource()) { //?try_safe29            resource.process(); //?process_safe30        }3132        // Idempotent close //?idempotent33        System.out.println("\n--- Idempotent Close ---");3435        try (IdempotentResource resource = new IdempotentResource()) { //?try_idempotent36            resource.use(); //?use_idempotent37            resource.close(); //?manual_close38            resource.close(); //?manual_close239            // Will be called again automatically //?auto_close_comment40        }4142        // Resource with cleanup action //?cleanup_action43        System.out.println("\n--- Resource with Cleanup Callback ---");4445        try (CallbackResource resource = new CallbackResource( //?try_callback46                () -> System.out.println("  [Cleanup] Resources freed!"))) { //?callback_lambda47            resource.process(); //?process_callback48        }4950        System.out.println("\n=== Key Points ===");51        System.out.println("""52            1. Implement AutoCloseable interface53            2. close() should be idempotent (safe to call multiple times)54            3. Don't throw exceptions in close() if possible55            4. Track state to prevent use after close56            5. Consider what cleanup is actually needed57            """);58    }59}6061// Timer resource - measures elapsed time //?timer_class62class Timer implements AutoCloseable { //?timer_def63    private final String operationName; //?operation_name64    private long elapsedMs = 0; //?elapsed_field6566    public Timer(String operationName) { //?timer_constructor67        this.operationName = operationName;68        System.out.println("  [Timer] Started: " + operationName); //?print_started69    }7071    public void simulateWork(long millis) { //?simulate_work_method72        elapsedMs += millis; //?add_elapsed73    }7475    @Override76    public void close() { //?timer_close77        System.out.println("  [Timer] " + operationNameoperation + " took " + elapsedMs100 + "ms"); //?print_elapsed78    }
    output  [Timer] operation took 100ms
    
    --- Stateful Resource ---
  6. try (Counter counter = new Counter())

    18try (Counter counter⟨Counter B⟩ = new Counter()) { //?try_counter19    counter.increment(); //?inc120    counter.increment(); //?inc2
  7. count ← 1

    pass 1 of 4
    18        try (Counter counter = new Counter()) { //?try_counter19            counter.increment(); //?inc120            counter.increment(); //?inc221            counter.increment(); //?inc322            System.out.println("  Count: " + counter.getCount()); //?print_count23        }2425        // Resource that can fail on close //?fail_on_close26        System.out.println("\n--- Resource That May Fail on Close ---");2728        try (SafeResource resource = new SafeResource()) { //?try_safe29            resource.process(); //?process_safe30        }3132        // Idempotent close //?idempotent33        System.out.println("\n--- Idempotent Close ---");3435        try (IdempotentResource resource = new IdempotentResource()) { //?try_idempotent36            resource.use(); //?use_idempotent37            resource.close(); //?manual_close38            resource.close(); //?manual_close239            // Will be called again automatically //?auto_close_comment40        }4142        // Resource with cleanup action //?cleanup_action43        System.out.println("\n--- Resource with Cleanup Callback ---");4445        try (CallbackResource resource = new CallbackResource( //?try_callback46                () -> System.out.println("  [Cleanup] Resources freed!"))) { //?callback_lambda47            resource.process(); //?process_callback48        }4950        System.out.println("\n=== Key Points ===");51        System.out.println("""52            1. Implement AutoCloseable interface53            2. close() should be idempotent (safe to call multiple times)54            3. Don't throw exceptions in close() if possible55            4. Track state to prevent use after close56            5. Consider what cleanup is actually needed57            """);58    }59}6061// Timer resource - measures elapsed time //?timer_class62class Timer implements AutoCloseable { //?timer_def63    private final String operationName; //?operation_name64    private long elapsedMs = 0; //?elapsed_field6566    public Timer(String operationName) { //?timer_constructor67        this.operationName = operationName;68        System.out.println("  [Timer] Started: " + operationName); //?print_started69    }7071    public void simulateWork(long millis) { //?simulate_work_method72        elapsedMs += millis; //?add_elapsed73    }7475    @Override76    public void close() { //?timer_close77        System.out.println("  [Timer] " + operationName + " took " + elapsedMs + "ms"); //?print_elapsed78    }79}8081// Counter resource - tracks count //?counter_class82class Counter implements AutoCloseable { //?counter_def83    private int count = 0; //?count_field84    private boolean closed = false; //?closed_field8586    public void increment() { //?increment_method87        checkNotClosed(); //?check_increment88        count→ 1++; //?do_increment89    }9091    public int getCount() { //?get_count92        checkNotClosed(); //?check_get93        return count; //?return_count94    }9596    private void checkNotClosed() { //?check_not_closed97        if (closed) { //?if_closed
    All 4 passes — pass 1 is the card above
    passcount
    10 1
    21 2
    32 3
    43
  8. System.out.println(" Count: " + counter.getCount()); //?print_count

    21    counter.increment(); //?inc322    System.out.println("  Count: " + counter.getCount()); //?print_count23}
    output  Count: 3
  9. closed ← true

    25        // Resource that can fail on close //?fail_on_close26        System.out.println("\n--- Resource That May Fail on Close ---");2728        try (SafeResource resource = new SafeResource()) { //?try_safe29            resource.process(); //?process_safe30        }3132        // Idempotent close //?idempotent33        System.out.println("\n--- Idempotent Close ---");3435        try (IdempotentResource resource = new IdempotentResource()) { //?try_idempotent36            resource.use(); //?use_idempotent37            resource.close(); //?manual_close38            resource.close(); //?manual_close239            // Will be called again automatically //?auto_close_comment40        }4142        // Resource with cleanup action //?cleanup_action43        System.out.println("\n--- Resource with Cleanup Callback ---");4445        try (CallbackResource resource = new CallbackResource( //?try_callback46                () -> System.out.println("  [Cleanup] Resources freed!"))) { //?callback_lambda47            resource.process(); //?process_callback48        }4950        System.out.println("\n=== Key Points ===");51        System.out.println("""52            1. Implement AutoCloseable interface53            2. close() should be idempotent (safe to call multiple times)54            3. Don't throw exceptions in close() if possible55            4. Track state to prevent use after close56            5. Consider what cleanup is actually needed57            """);58    }59}6061// Timer resource - measures elapsed time //?timer_class62class Timer implements AutoCloseable { //?timer_def63    private final String operationName; //?operation_name64    private long elapsedMs = 0; //?elapsed_field6566    public Timer(String operationName) { //?timer_constructor67        this.operationName = operationName;68        System.out.println("  [Timer] Started: " + operationName); //?print_started69    }7071    public void simulateWork(long millis) { //?simulate_work_method72        elapsedMs += millis; //?add_elapsed73    }7475    @Override76    public void close() { //?timer_close77        System.out.println("  [Timer] " + operationName + " took " + elapsedMs + "ms"); //?print_elapsed78    }79}8081// Counter resource - tracks count //?counter_class82class Counter implements AutoCloseable { //?counter_def83    private int count = 0; //?count_field84    private boolean closed = false; //?closed_field8586    public void increment() { //?increment_method87        checkNotClosed(); //?check_increment88        count++; //?do_increment89    }9091    public int getCount() { //?get_count92        checkNotClosed(); //?check_get93        return count; //?return_count94    }9596    private void checkNotClosed() { //?check_not_closed97        if (closed) { //?if_closed98            throw new IllegalStateException("Counter is closed"); //?throw_closed99        }100    }101102    @Override103    public void close() { //?counter_close104        if (!closedfalse) { //?if_not_closed105            System.out.println("  [Counter] Final count: " + count3); //?print_final106            closed→ true = true; //?set_closed107        }
    output  [Counter] Final count: 3
    
    --- Resource That May Fail on Close ---
  10. try (SafeResource resource = new SafeResource())

    28try (SafeResource resource⟨SafeResource C⟩ = new SafeResource()) { //?try_safe29    resource.process(); //?process_safe30}
  11. public void process()

    28        try (SafeResource resource = new SafeResource()) { //?try_safe29            resource.process(); //?process_safe30        }3132        // Idempotent close //?idempotent33        System.out.println("\n--- Idempotent Close ---");3435        try (IdempotentResource resource = new IdempotentResource()) { //?try_idempotent36            resource.use(); //?use_idempotent37            resource.close(); //?manual_close38            resource.close(); //?manual_close239            // Will be called again automatically //?auto_close_comment40        }4142        // Resource with cleanup action //?cleanup_action43        System.out.println("\n--- Resource with Cleanup Callback ---");4445        try (CallbackResource resource = new CallbackResource( //?try_callback46                () -> System.out.println("  [Cleanup] Resources freed!"))) { //?callback_lambda47            resource.process(); //?process_callback48        }4950        System.out.println("\n=== Key Points ===");51        System.out.println("""52            1. Implement AutoCloseable interface53            2. close() should be idempotent (safe to call multiple times)54            3. Don't throw exceptions in close() if possible55            4. Track state to prevent use after close56            5. Consider what cleanup is actually needed57            """);58    }59}6061// Timer resource - measures elapsed time //?timer_class62class Timer implements AutoCloseable { //?timer_def63    private final String operationName; //?operation_name64    private long elapsedMs = 0; //?elapsed_field6566    public Timer(String operationName) { //?timer_constructor67        this.operationName = operationName;68        System.out.println("  [Timer] Started: " + operationName); //?print_started69    }7071    public void simulateWork(long millis) { //?simulate_work_method72        elapsedMs += millis; //?add_elapsed73    }7475    @Override76    public void close() { //?timer_close77        System.out.println("  [Timer] " + operationName + " took " + elapsedMs + "ms"); //?print_elapsed78    }79}8081// Counter resource - tracks count //?counter_class82class Counter implements AutoCloseable { //?counter_def83    private int count = 0; //?count_field84    private boolean closed = false; //?closed_field8586    public void increment() { //?increment_method87        checkNotClosed(); //?check_increment88        count++; //?do_increment89    }9091    public int getCount() { //?get_count92        checkNotClosed(); //?check_get93        return count; //?return_count94    }9596    private void checkNotClosed() { //?check_not_closed97        if (closed) { //?if_closed98            throw new IllegalStateException("Counter is closed"); //?throw_closed99        }100    }101102    @Override103    public void close() { //?counter_close104        if (!closed) { //?if_not_closed105            System.out.println("  [Counter] Final count: " + count); //?print_final106            closed = true; //?set_closed107        }108    }109}110111// Resource that handles close errors gracefully //?safe_resource_class112class SafeResource implements AutoCloseable { //?safe_resource_def113114    public void process() { //?process_method115        System.out.println("  [SafeResource] Processing..."); //?print_processing116    }
    output  [SafeResource] Processing...
  12. @Override public void close()

    118@Override119public void close() { //?safe_close120    System.out.println("  [SafeResource] Closing..."); //?print_closing121    try { //?try_cleanup
    output  [SafeResource] Closing...
  13. private void performCleanup()

    32        // Idempotent close //?idempotent33        System.out.println("\n--- Idempotent Close ---");3435        try (IdempotentResource resource = new IdempotentResource()) { //?try_idempotent36            resource.use(); //?use_idempotent37            resource.close(); //?manual_close38            resource.close(); //?manual_close239            // Will be called again automatically //?auto_close_comment40        }4142        // Resource with cleanup action //?cleanup_action43        System.out.println("\n--- Resource with Cleanup Callback ---");4445        try (CallbackResource resource = new CallbackResource( //?try_callback46                () -> System.out.println("  [Cleanup] Resources freed!"))) { //?callback_lambda47            resource.process(); //?process_callback48        }4950        System.out.println("\n=== Key Points ===");51        System.out.println("""52            1. Implement AutoCloseable interface53            2. close() should be idempotent (safe to call multiple times)54            3. Don't throw exceptions in close() if possible55            4. Track state to prevent use after close56            5. Consider what cleanup is actually needed57            """);58    }59}6061// Timer resource - measures elapsed time //?timer_class62class Timer implements AutoCloseable { //?timer_def63    private final String operationName; //?operation_name64    private long elapsedMs = 0; //?elapsed_field6566    public Timer(String operationName) { //?timer_constructor67        this.operationName = operationName;68        System.out.println("  [Timer] Started: " + operationName); //?print_started69    }7071    public void simulateWork(long millis) { //?simulate_work_method72        elapsedMs += millis; //?add_elapsed73    }7475    @Override76    public void close() { //?timer_close77        System.out.println("  [Timer] " + operationName + " took " + elapsedMs + "ms"); //?print_elapsed78    }79}8081// Counter resource - tracks count //?counter_class82class Counter implements AutoCloseable { //?counter_def83    private int count = 0; //?count_field84    private boolean closed = false; //?closed_field8586    public void increment() { //?increment_method87        checkNotClosed(); //?check_increment88        count++; //?do_increment89    }9091    public int getCount() { //?get_count92        checkNotClosed(); //?check_get93        return count; //?return_count94    }9596    private void checkNotClosed() { //?check_not_closed97        if (closed) { //?if_closed98            throw new IllegalStateException("Counter is closed"); //?throw_closed99        }100    }101102    @Override103    public void close() { //?counter_close104        if (!closed) { //?if_not_closed105            System.out.println("  [Counter] Final count: " + count); //?print_final106            closed = true; //?set_closed107        }108    }109}110111// Resource that handles close errors gracefully //?safe_resource_class112class SafeResource implements AutoCloseable { //?safe_resource_def113114    public void process() { //?process_method115        System.out.println("  [SafeResource] Processing..."); //?print_processing116    }117118    @Override119    public void close() { //?safe_close120        System.out.println("  [SafeResource] Closing..."); //?print_closing121        try { //?try_cleanup122            // Simulate cleanup that might fail //?simulate_cleanup123            performCleanup(); //?do_cleanup124        } catch (Exception e) { //?catch_cleanup125            // Log but don't rethrow //?log_comment126            System.out.println("  [SafeResource] Cleanup warning: " + e.getMessage()); //?print_warning127        }128        System.out.println("  [SafeResource] Closed (even if cleanup had issues)"); //?print_closed129    }130131    private void performCleanup() { //?perform_cleanup132        // In real code, this might fail //?might_fail133        System.out.println("  [SafeResource] Cleanup succeeded"); //?cleanup_success134    }
    output  [SafeResource] Cleanup succeeded
      [SafeResource] Closed (even if cleanup had issues)
    
    --- Idempotent Close ---
  14. try (IdempotentResource resource = new IdempotentResource())

    35try (IdempotentResource resource⟨IdempotentResource D⟩ = new IdempotentResource()) { //?try_idempotent36    resource.use(); //?use_idempotent37    resource.close(); //?manual_close
  15. public void use()

    35        try (IdempotentResource resource = new IdempotentResource()) { //?try_idempotent36            resource.use(); //?use_idempotent37            resource.close(); //?manual_close38            resource.close(); //?manual_close239            // Will be called again automatically //?auto_close_comment40        }4142        // Resource with cleanup action //?cleanup_action43        System.out.println("\n--- Resource with Cleanup Callback ---");4445        try (CallbackResource resource = new CallbackResource( //?try_callback46                () -> System.out.println("  [Cleanup] Resources freed!"))) { //?callback_lambda47            resource.process(); //?process_callback48        }4950        System.out.println("\n=== Key Points ===");51        System.out.println("""52            1. Implement AutoCloseable interface53            2. close() should be idempotent (safe to call multiple times)54            3. Don't throw exceptions in close() if possible55            4. Track state to prevent use after close56            5. Consider what cleanup is actually needed57            """);58    }59}6061// Timer resource - measures elapsed time //?timer_class62class Timer implements AutoCloseable { //?timer_def63    private final String operationName; //?operation_name64    private long elapsedMs = 0; //?elapsed_field6566    public Timer(String operationName) { //?timer_constructor67        this.operationName = operationName;68        System.out.println("  [Timer] Started: " + operationName); //?print_started69    }7071    public void simulateWork(long millis) { //?simulate_work_method72        elapsedMs += millis; //?add_elapsed73    }7475    @Override76    public void close() { //?timer_close77        System.out.println("  [Timer] " + operationName + " took " + elapsedMs + "ms"); //?print_elapsed78    }79}8081// Counter resource - tracks count //?counter_class82class Counter implements AutoCloseable { //?counter_def83    private int count = 0; //?count_field84    private boolean closed = false; //?closed_field8586    public void increment() { //?increment_method87        checkNotClosed(); //?check_increment88        count++; //?do_increment89    }9091    public int getCount() { //?get_count92        checkNotClosed(); //?check_get93        return count; //?return_count94    }9596    private void checkNotClosed() { //?check_not_closed97        if (closed) { //?if_closed98            throw new IllegalStateException("Counter is closed"); //?throw_closed99        }100    }101102    @Override103    public void close() { //?counter_close104        if (!closed) { //?if_not_closed105            System.out.println("  [Counter] Final count: " + count); //?print_final106            closed = true; //?set_closed107        }108    }109}110111// Resource that handles close errors gracefully //?safe_resource_class112class SafeResource implements AutoCloseable { //?safe_resource_def113114    public void process() { //?process_method115        System.out.println("  [SafeResource] Processing..."); //?print_processing116    }117118    @Override119    public void close() { //?safe_close120        System.out.println("  [SafeResource] Closing..."); //?print_closing121        try { //?try_cleanup122            // Simulate cleanup that might fail //?simulate_cleanup123            performCleanup(); //?do_cleanup124        } catch (Exception e) { //?catch_cleanup125            // Log but don't rethrow //?log_comment126            System.out.println("  [SafeResource] Cleanup warning: " + e.getMessage()); //?print_warning127        }128        System.out.println("  [SafeResource] Closed (even if cleanup had issues)"); //?print_closed129    }130131    private void performCleanup() { //?perform_cleanup132        // In real code, this might fail //?might_fail133        System.out.println("  [SafeResource] Cleanup succeeded"); //?cleanup_success134    }135}136137// Resource with idempotent close //?idempotent_class138class IdempotentResource implements AutoCloseable { //?idempotent_def139    private boolean closed = false; //?idempotent_closed140    private int closeCallCount = 0; //?close_call_count141142    public void use() { //?use_method143        if (closed) throw new IllegalStateException("Already closed"); //?check_use144        System.out.println("  [Idempotent] Using resource"); //?print_using145    }
    output  [Idempotent] Using resource
  16. closeCallCount ← 1

    pass 1 of 3
    147@Override148public void close() { //?idempotent_close149    closeCallCount→ 1++; //?increment_count150    System.out.println("  [Idempotent] close() called (call #" + closeCallCount1 + ")"); //?print_call
    output  [Idempotent] close() called (call #1)
    All 3 passes — pass 1 is the card above
    passcleanupActionresourcecloseCallCountclosedthis.cleanupAction
    10 1false true
    21 2
    3⟨CustomAutocloseable lambda E⟩⟨CallbackResource F⟩2 3⟨CustomAutocloseable lambda E⟩
  17. closed ← true

    36            resource.use(); //?use_idempotent37            resource.close(); //?manual_close38            resource.close(); //?manual_close239            // Will be called again automatically //?auto_close_comment40        }4142        // Resource with cleanup action //?cleanup_action43        System.out.println("\n--- Resource with Cleanup Callback ---");4445        try (CallbackResource resource = new CallbackResource( //?try_callback46                () -> System.out.println("  [Cleanup] Resources freed!"))) { //?callback_lambda47            resource.process(); //?process_callback48        }4950        System.out.println("\n=== Key Points ===");51        System.out.println("""52            1. Implement AutoCloseable interface53            2. close() should be idempotent (safe to call multiple times)54            3. Don't throw exceptions in close() if possible55            4. Track state to prevent use after close56            5. Consider what cleanup is actually needed57            """);58    }59}6061// Timer resource - measures elapsed time //?timer_class62class Timer implements AutoCloseable { //?timer_def63    private final String operationName; //?operation_name64    private long elapsedMs = 0; //?elapsed_field6566    public Timer(String operationName) { //?timer_constructor67        this.operationName = operationName;68        System.out.println("  [Timer] Started: " + operationName); //?print_started69    }7071    public void simulateWork(long millis) { //?simulate_work_method72        elapsedMs += millis; //?add_elapsed73    }7475    @Override76    public void close() { //?timer_close77        System.out.println("  [Timer] " + operationName + " took " + elapsedMs + "ms"); //?print_elapsed78    }79}8081// Counter resource - tracks count //?counter_class82class Counter implements AutoCloseable { //?counter_def83    private int count = 0; //?count_field84    private boolean closed = false; //?closed_field8586    public void increment() { //?increment_method87        checkNotClosed(); //?check_increment88        count++; //?do_increment89    }9091    public int getCount() { //?get_count92        checkNotClosed(); //?check_get93        return count; //?return_count94    }9596    private void checkNotClosed() { //?check_not_closed97        if (closed) { //?if_closed98            throw new IllegalStateException("Counter is closed"); //?throw_closed99        }100    }101102    @Override103    public void close() { //?counter_close104        if (!closed) { //?if_not_closed105            System.out.println("  [Counter] Final count: " + count); //?print_final106            closed = true; //?set_closed107        }108    }109}110111// Resource that handles close errors gracefully //?safe_resource_class112class SafeResource implements AutoCloseable { //?safe_resource_def113114    public void process() { //?process_method115        System.out.println("  [SafeResource] Processing..."); //?print_processing116    }117118    @Override119    public void close() { //?safe_close120        System.out.println("  [SafeResource] Closing..."); //?print_closing121        try { //?try_cleanup122            // Simulate cleanup that might fail //?simulate_cleanup123            performCleanup(); //?do_cleanup124        } catch (Exception e) { //?catch_cleanup125            // Log but don't rethrow //?log_comment126            System.out.println("  [SafeResource] Cleanup warning: " + e.getMessage()); //?print_warning127        }128        System.out.println("  [SafeResource] Closed (even if cleanup had issues)"); //?print_closed129    }130131    private void performCleanup() { //?perform_cleanup132        // In real code, this might fail //?might_fail133        System.out.println("  [SafeResource] Cleanup succeeded"); //?cleanup_success134    }135}136137// Resource with idempotent close //?idempotent_class138class IdempotentResource implements AutoCloseable { //?idempotent_def139    private boolean closed = false; //?idempotent_closed140    private int closeCallCount = 0; //?close_call_count141142    public void use() { //?use_method143        if (closed) throw new IllegalStateException("Already closed"); //?check_use144        System.out.println("  [Idempotent] Using resource"); //?print_using145    }146147    @Override148    public void close() { //?idempotent_close149        closeCallCount++; //?increment_count150        System.out.println("  [Idempotent] close() called (call #" + closeCallCount + ")"); //?print_call151152        if (!closedfalse) { //?first_close_check153            closed→ true = true; //?do_close154            System.out.println("  [Idempotent] Actually closing resources"); //?actually_close155        } else {
    output  [Idempotent] Actually closing resources
  18. else

    pass 1 of 2
    37            resource.close(); //?manual_close38            resource.close(); //?manual_close239            // Will be called again automatically //?auto_close_comment40        }4142        // Resource with cleanup action //?cleanup_action43        System.out.println("\n--- Resource with Cleanup Callback ---");4445        try (CallbackResource resource = new CallbackResource( //?try_callback46                () -> System.out.println("  [Cleanup] Resources freed!"))) { //?callback_lambda47            resource.process(); //?process_callback48        }4950        System.out.println("\n=== Key Points ===");51        System.out.println("""52            1. Implement AutoCloseable interface53            2. close() should be idempotent (safe to call multiple times)54            3. Don't throw exceptions in close() if possible55            4. Track state to prevent use after close56            5. Consider what cleanup is actually needed57            """);58    }59}6061// Timer resource - measures elapsed time //?timer_class62class Timer implements AutoCloseable { //?timer_def63    private final String operationName; //?operation_name64    private long elapsedMs = 0; //?elapsed_field6566    public Timer(String operationName) { //?timer_constructor67        this.operationName = operationName;68        System.out.println("  [Timer] Started: " + operationName); //?print_started69    }7071    public void simulateWork(long millis) { //?simulate_work_method72        elapsedMs += millis; //?add_elapsed73    }7475    @Override76    public void close() { //?timer_close77        System.out.println("  [Timer] " + operationName + " took " + elapsedMs + "ms"); //?print_elapsed78    }79}8081// Counter resource - tracks count //?counter_class82class Counter implements AutoCloseable { //?counter_def83    private int count = 0; //?count_field84    private boolean closed = false; //?closed_field8586    public void increment() { //?increment_method87        checkNotClosed(); //?check_increment88        count++; //?do_increment89    }9091    public int getCount() { //?get_count92        checkNotClosed(); //?check_get93        return count; //?return_count94    }9596    private void checkNotClosed() { //?check_not_closed97        if (closed) { //?if_closed98            throw new IllegalStateException("Counter is closed"); //?throw_closed99        }100    }101102    @Override103    public void close() { //?counter_close104        if (!closed) { //?if_not_closed105            System.out.println("  [Counter] Final count: " + count); //?print_final106            closed = true; //?set_closed107        }108    }109}110111// Resource that handles close errors gracefully //?safe_resource_class112class SafeResource implements AutoCloseable { //?safe_resource_def113114    public void process() { //?process_method115        System.out.println("  [SafeResource] Processing..."); //?print_processing116    }117118    @Override119    public void close() { //?safe_close120        System.out.println("  [SafeResource] Closing..."); //?print_closing121        try { //?try_cleanup122            // Simulate cleanup that might fail //?simulate_cleanup123            performCleanup(); //?do_cleanup124        } catch (Exception e) { //?catch_cleanup125            // Log but don't rethrow //?log_comment126            System.out.println("  [SafeResource] Cleanup warning: " + e.getMessage()); //?print_warning127        }128        System.out.println("  [SafeResource] Closed (even if cleanup had issues)"); //?print_closed129    }130131    private void performCleanup() { //?perform_cleanup132        // In real code, this might fail //?might_fail133        System.out.println("  [SafeResource] Cleanup succeeded"); //?cleanup_success134    }135}136137// Resource with idempotent close //?idempotent_class138class IdempotentResource implements AutoCloseable { //?idempotent_def139    private boolean closed = false; //?idempotent_closed140    private int closeCallCount = 0; //?close_call_count141142    public void use() { //?use_method143        if (closed) throw new IllegalStateException("Already closed"); //?check_use144        System.out.println("  [Idempotent] Using resource"); //?print_using145    }146147    @Override148    public void close() { //?idempotent_close149        closeCallCount++; //?increment_count150        System.out.println("  [Idempotent] close() called (call #" + closeCallCount + ")"); //?print_call151152        if (!closed) { //?first_close_check153            closed = true; //?do_close154            System.out.println("  [Idempotent] Actually closing resources"); //?actually_close155        } else {156            System.out.println("  [Idempotent] Already closed, doing nothing"); //?already_closed157        }
    output  [Idempotent] Already closed, doing nothing
  19. else

    pass 2 of 2
    42        // Resource with cleanup action //?cleanup_action43        System.out.println("\n--- Resource with Cleanup Callback ---");4445        try (CallbackResource resource = new CallbackResource( //?try_callback46                () -> System.out.println("  [Cleanup] Resources freed!"))) { //?callback_lambda47            resource.process(); //?process_callback48        }4950        System.out.println("\n=== Key Points ===");51        System.out.println("""52            1. Implement AutoCloseable interface53            2. close() should be idempotent (safe to call multiple times)54            3. Don't throw exceptions in close() if possible55            4. Track state to prevent use after close56            5. Consider what cleanup is actually needed57            """);58    }59}6061// Timer resource - measures elapsed time //?timer_class62class Timer implements AutoCloseable { //?timer_def63    private final String operationName; //?operation_name64    private long elapsedMs = 0; //?elapsed_field6566    public Timer(String operationName) { //?timer_constructor67        this.operationName = operationName;68        System.out.println("  [Timer] Started: " + operationName); //?print_started69    }7071    public void simulateWork(long millis) { //?simulate_work_method72        elapsedMs += millis; //?add_elapsed73    }7475    @Override76    public void close() { //?timer_close77        System.out.println("  [Timer] " + operationName + " took " + elapsedMs + "ms"); //?print_elapsed78    }79}8081// Counter resource - tracks count //?counter_class82class Counter implements AutoCloseable { //?counter_def83    private int count = 0; //?count_field84    private boolean closed = false; //?closed_field8586    public void increment() { //?increment_method87        checkNotClosed(); //?check_increment88        count++; //?do_increment89    }9091    public int getCount() { //?get_count92        checkNotClosed(); //?check_get93        return count; //?return_count94    }9596    private void checkNotClosed() { //?check_not_closed97        if (closed) { //?if_closed98            throw new IllegalStateException("Counter is closed"); //?throw_closed99        }100    }101102    @Override103    public void close() { //?counter_close104        if (!closed) { //?if_not_closed105            System.out.println("  [Counter] Final count: " + count); //?print_final106            closed = true; //?set_closed107        }108    }109}110111// Resource that handles close errors gracefully //?safe_resource_class112class SafeResource implements AutoCloseable { //?safe_resource_def113114    public void process() { //?process_method115        System.out.println("  [SafeResource] Processing..."); //?print_processing116    }117118    @Override119    public void close() { //?safe_close120        System.out.println("  [SafeResource] Closing..."); //?print_closing121        try { //?try_cleanup122            // Simulate cleanup that might fail //?simulate_cleanup123            performCleanup(); //?do_cleanup124        } catch (Exception e) { //?catch_cleanup125            // Log but don't rethrow //?log_comment126            System.out.println("  [SafeResource] Cleanup warning: " + e.getMessage()); //?print_warning127        }128        System.out.println("  [SafeResource] Closed (even if cleanup had issues)"); //?print_closed129    }130131    private void performCleanup() { //?perform_cleanup132        // In real code, this might fail //?might_fail133        System.out.println("  [SafeResource] Cleanup succeeded"); //?cleanup_success134    }135}136137// Resource with idempotent close //?idempotent_class138class IdempotentResource implements AutoCloseable { //?idempotent_def139    private boolean closed = false; //?idempotent_closed140    private int closeCallCount = 0; //?close_call_count141142    public void use() { //?use_method143        if (closed) throw new IllegalStateException("Already closed"); //?check_use144        System.out.println("  [Idempotent] Using resource"); //?print_using145    }146147    @Override148    public void close() { //?idempotent_close149        closeCallCount++; //?increment_count150        System.out.println("  [Idempotent] close() called (call #" + closeCallCount + ")"); //?print_call151152        if (!closed) { //?first_close_check153            closed = true; //?do_close154            System.out.println("  [Idempotent] Actually closing resources"); //?actually_close155        } else {156            System.out.println("  [Idempotent] Already closed, doing nothing"); //?already_closed157        }
    output  [Idempotent] Already closed, doing nothing
    
    --- Resource with Cleanup Callback ---
  20. this.cleanupAction ← ⟨CustomAutocloseable lambda E⟩

    165public CallbackResource(Runnable cleanupAction⟨CustomAutocloseable lambda E⟩) { //?callback_constructor166    this.cleanupAction→ ⟨CustomAutocloseable lambda E⟩ = cleanupAction⟨CustomAutocloseable lambda E⟩;167    System.out.println("  [Callback] Resource created"); //?print_created168}
    output  [Callback] Resource created
  21. try (CallbackResource resource = new CallbackResource( //?try_callback…

    45try (CallbackResource resource⟨CallbackResource F⟩ = new CallbackResource( //?try_callback46        () -> System.out.println("  [Cleanup] Resources freed!"))) { //?callback_lambda47    resource.process(); //?process_callback48}
  22. public void process()

    46                () -> System.out.println("  [Cleanup] Resources freed!"))) { //?callback_lambda47            resource.process(); //?process_callback48        }4950        System.out.println("\n=== Key Points ===");51        System.out.println("""52            1. Implement AutoCloseable interface53            2. close() should be idempotent (safe to call multiple times)54            3. Don't throw exceptions in close() if possible55            4. Track state to prevent use after close56            5. Consider what cleanup is actually needed57            """);58    }59}6061// Timer resource - measures elapsed time //?timer_class62class Timer implements AutoCloseable { //?timer_def63    private final String operationName; //?operation_name64    private long elapsedMs = 0; //?elapsed_field6566    public Timer(String operationName) { //?timer_constructor67        this.operationName = operationName;68        System.out.println("  [Timer] Started: " + operationName); //?print_started69    }7071    public void simulateWork(long millis) { //?simulate_work_method72        elapsedMs += millis; //?add_elapsed73    }7475    @Override76    public void close() { //?timer_close77        System.out.println("  [Timer] " + operationName + " took " + elapsedMs + "ms"); //?print_elapsed78    }79}8081// Counter resource - tracks count //?counter_class82class Counter implements AutoCloseable { //?counter_def83    private int count = 0; //?count_field84    private boolean closed = false; //?closed_field8586    public void increment() { //?increment_method87        checkNotClosed(); //?check_increment88        count++; //?do_increment89    }9091    public int getCount() { //?get_count92        checkNotClosed(); //?check_get93        return count; //?return_count94    }9596    private void checkNotClosed() { //?check_not_closed97        if (closed) { //?if_closed98            throw new IllegalStateException("Counter is closed"); //?throw_closed99        }100    }101102    @Override103    public void close() { //?counter_close104        if (!closed) { //?if_not_closed105            System.out.println("  [Counter] Final count: " + count); //?print_final106            closed = true; //?set_closed107        }108    }109}110111// Resource that handles close errors gracefully //?safe_resource_class112class SafeResource implements AutoCloseable { //?safe_resource_def113114    public void process() { //?process_method115        System.out.println("  [SafeResource] Processing..."); //?print_processing116    }117118    @Override119    public void close() { //?safe_close120        System.out.println("  [SafeResource] Closing..."); //?print_closing121        try { //?try_cleanup122            // Simulate cleanup that might fail //?simulate_cleanup123            performCleanup(); //?do_cleanup124        } catch (Exception e) { //?catch_cleanup125            // Log but don't rethrow //?log_comment126            System.out.println("  [SafeResource] Cleanup warning: " + e.getMessage()); //?print_warning127        }128        System.out.println("  [SafeResource] Closed (even if cleanup had issues)"); //?print_closed129    }130131    private void performCleanup() { //?perform_cleanup132        // In real code, this might fail //?might_fail133        System.out.println("  [SafeResource] Cleanup succeeded"); //?cleanup_success134    }135}136137// Resource with idempotent close //?idempotent_class138class IdempotentResource implements AutoCloseable { //?idempotent_def139    private boolean closed = false; //?idempotent_closed140    private int closeCallCount = 0; //?close_call_count141142    public void use() { //?use_method143        if (closed) throw new IllegalStateException("Already closed"); //?check_use144        System.out.println("  [Idempotent] Using resource"); //?print_using145    }146147    @Override148    public void close() { //?idempotent_close149        closeCallCount++; //?increment_count150        System.out.println("  [Idempotent] close() called (call #" + closeCallCount + ")"); //?print_call151152        if (!closed) { //?first_close_check153            closed = true; //?do_close154            System.out.println("  [Idempotent] Actually closing resources"); //?actually_close155        } else {156            System.out.println("  [Idempotent] Already closed, doing nothing"); //?already_closed157        }158    }159}160161// Resource with cleanup callback //?callback_class162class CallbackResource implements AutoCloseable { //?callback_def163    private final Runnable cleanupAction; //?cleanup_action_field164165    public CallbackResource(Runnable cleanupAction) { //?callback_constructor166        this.cleanupAction = cleanupAction;167        System.out.println("  [Callback] Resource created"); //?print_created168    }169170    public void process() { //?callback_process171        System.out.println("  [Callback] Processing..."); //?print_callback_process172    }
    output  [Callback] Processing...
  23. @Override public void close()

    50        System.out.println("\n=== Key Points ===");51        System.out.println("""52            1. Implement AutoCloseable interface53            2. close() should be idempotent (safe to call multiple times)54            3. Don't throw exceptions in close() if possible55            4. Track state to prevent use after close56            5. Consider what cleanup is actually needed57            """);58    }59}6061// Timer resource - measures elapsed time //?timer_class62class Timer implements AutoCloseable { //?timer_def63    private final String operationName; //?operation_name64    private long elapsedMs = 0; //?elapsed_field6566    public Timer(String operationName) { //?timer_constructor67        this.operationName = operationName;68        System.out.println("  [Timer] Started: " + operationName); //?print_started69    }7071    public void simulateWork(long millis) { //?simulate_work_method72        elapsedMs += millis; //?add_elapsed73    }7475    @Override76    public void close() { //?timer_close77        System.out.println("  [Timer] " + operationName + " took " + elapsedMs + "ms"); //?print_elapsed78    }79}8081// Counter resource - tracks count //?counter_class82class Counter implements AutoCloseable { //?counter_def83    private int count = 0; //?count_field84    private boolean closed = false; //?closed_field8586    public void increment() { //?increment_method87        checkNotClosed(); //?check_increment88        count++; //?do_increment89    }9091    public int getCount() { //?get_count92        checkNotClosed(); //?check_get93        return count; //?return_count94    }9596    private void checkNotClosed() { //?check_not_closed97        if (closed) { //?if_closed98            throw new IllegalStateException("Counter is closed"); //?throw_closed99        }100    }101102    @Override103    public void close() { //?counter_close104        if (!closed) { //?if_not_closed105            System.out.println("  [Counter] Final count: " + count); //?print_final106            closed = true; //?set_closed107        }108    }109}110111// Resource that handles close errors gracefully //?safe_resource_class112class SafeResource implements AutoCloseable { //?safe_resource_def113114    public void process() { //?process_method115        System.out.println("  [SafeResource] Processing..."); //?print_processing116    }117118    @Override119    public void close() { //?safe_close120        System.out.println("  [SafeResource] Closing..."); //?print_closing121        try { //?try_cleanup122            // Simulate cleanup that might fail //?simulate_cleanup123            performCleanup(); //?do_cleanup124        } catch (Exception e) { //?catch_cleanup125            // Log but don't rethrow //?log_comment126            System.out.println("  [SafeResource] Cleanup warning: " + e.getMessage()); //?print_warning127        }128        System.out.println("  [SafeResource] Closed (even if cleanup had issues)"); //?print_closed129    }130131    private void performCleanup() { //?perform_cleanup132        // In real code, this might fail //?might_fail133        System.out.println("  [SafeResource] Cleanup succeeded"); //?cleanup_success134    }135}136137// Resource with idempotent close //?idempotent_class138class IdempotentResource implements AutoCloseable { //?idempotent_def139    private boolean closed = false; //?idempotent_closed140    private int closeCallCount = 0; //?close_call_count141142    public void use() { //?use_method143        if (closed) throw new IllegalStateException("Already closed"); //?check_use144        System.out.println("  [Idempotent] Using resource"); //?print_using145    }146147    @Override148    public void close() { //?idempotent_close149        closeCallCount++; //?increment_count150        System.out.println("  [Idempotent] close() called (call #" + closeCallCount + ")"); //?print_call151152        if (!closed) { //?first_close_check153            closed = true; //?do_close154            System.out.println("  [Idempotent] Actually closing resources"); //?actually_close155        } else {156            System.out.println("  [Idempotent] Already closed, doing nothing"); //?already_closed157        }158    }159}160161// Resource with cleanup callback //?callback_class162class CallbackResource implements AutoCloseable { //?callback_def163    private final Runnable cleanupAction; //?cleanup_action_field164165    public CallbackResource(Runnable cleanupAction) { //?callback_constructor166        this.cleanupAction = cleanupAction;167        System.out.println("  [Callback] Resource created"); //?print_created168    }169170    public void process() { //?callback_process171        System.out.println("  [Callback] Processing..."); //?print_callback_process172    }173174    @Override175    public void close() { //?callback_close176        System.out.println("  [Callback] Closing..."); //?print_callback_close177        cleanupAction.run(); //?run_cleanup178    }
    output  [Callback] Closing...
    
    === Key Points ===
    1. Implement AutoCloseable interface
    2. close() should be idempotent (safe to call multiple times)
    3. Don't throw exceptions in close() if possible
    4. Track state to prevent use after close
    5. Consider what cleanup is actually needed

Implement AutoCloseable interface with close() method.

AutoCloseable Interface with `close()` method. Enables try-with-resources.

Suppressed exceptions

Handle exceptions during close.

SuppressedExceptions.java
Replay: real traced execution (multi-file project)
// Understanding Suppressed Exceptions

public class SuppressedExceptions {
    public static void main(String[] args) {
        System.out.println("=== Suppressed Exceptions ===\n");

        // When both try body and close() throw
        System.out.println("--- Exception in Try Body AND close() ---");

        try {
            try (ThrowingResource resource = new ThrowingResource()) {
                resource.doWork();
                throw new RuntimeException("Error in try body");
            }
        } catch (Exception e) {
            System.out.println("Primary exception: " + e.getMessage());

            Throwable[] suppressed = e.getSuppressed();
            System.out.println("Suppressed exceptions: " + suppressed.length);

            for (Throwable t : suppressed) {
                System.out.println("  - " + t.getMessage());
            }
        }

        // Multiple resources, multiple close failures
        System.out.println("\n--- Multiple Resources Failing to Close ---");

        try {
            try (
                ThrowingResource r1 = new ThrowingResource("first");
                ThrowingResource r2 = new ThrowingResource("second");
                ThrowingResource r3 = new ThrowingResource("third")
            ) {
                throw new RuntimeException("Main error");
            }
        } catch (Exception e) {
            System.out.println("Primary: " + e.getMessage());
            System.out.println("Suppressed:");
            for (Throwable t : e.getSuppressed()) {
                System.out.println("  - " + t.getMessage());
            }
        }

        // Only close() throws (no exception in try body)
        System.out.println("\n--- Only close() Throws ---");

        try {
            try (ThrowingResource resource = new ThrowingResource()) {
                resource.doWork();
                System.out.println("  Work completed successfully");
                // No exception here
            }
        } catch (Exception e) {
            System.out.println("Exception from close(): " + e.getMessage());
            System.out.println("Suppressed: " + e.getSuppressed().length);
        }

        // Examining suppressed exceptions
        System.out.println("\n--- Examining Suppressed Exceptions ---");

        try {
            try (ExamineResource resource = new ExamineResource()) {
                throw new RuntimeException("Primary failure");
            }
        } catch (Exception e) {
            printExceptionTree(e, 0);
        }

        // Manually adding suppressed exceptions
        System.out.println("\n--- Manually Adding Suppressed ---");

        Exception primary = new Exception("Primary error");
        primary.addSuppressed(new Exception("Cleanup error 1"));
        primary.addSuppressed(new Exception("Cleanup error 2"));

        System.out.println("Primary: " + primary.getMessage());
        for (Throwable t : primary.getSuppressed()) {
            System.out.println("  Suppressed: " + t.getMessage());
        }

        System.out.println("\n=== Key Points ===");
        System.out.println("""
            1. If try body throws, that's the PRIMARY exception
            2. If close() also throws, it's SUPPRESSED
            3. Access suppressed via getSuppressed()
            4. Multiple close() failures → multiple suppressed
            5. If only close() throws, that becomes the primary
            6. Suppressed exceptions preserve all error information
            """);
    }

    static void printExceptionTree(Throwable t, int indent) {
        String prefix = "  ".repeat(indent);
        System.out.println(prefix + "Exception: " + t.getClass().getSimpleName());
        System.out.println(prefix + "  Message: " + t.getMessage());

        Throwable[] suppressed = t.getSuppressed();
        if (suppressed.length > 0) {
            System.out.println(prefix + "  Suppressed:");
            for (Throwable s : suppressed) {
                printExceptionTree(s, indent + 2);
            }
        }

        if (t.getCause() != null) {
            System.out.println(prefix + "  Caused by:");
            printExceptionTree(t.getCause(), indent + 2);
        }
    }
}

// Resource that throws on close
class ThrowingResource implements AutoCloseable {
    private final String name;

    public ThrowingResource() {
        this("default");
    }

    public ThrowingResource(String name) {
        this.name = name;
        System.out.println("  [" + name + "] Opened");
    }

    public void doWork() {
        System.out.println("  [" + name + "] Working...");
    }

    @Override
    public void close() {
        System.out.println("  [" + name + "] Closing (will throw)...");
        throw new RuntimeException("Error closing " + name);
    }
}

// Resource for examining exception tree
class ExamineResource implements AutoCloseable {

    public ExamineResource() {
        System.out.println("  [ExamineResource] Opened");
    }

    @Override
    public void close() {
        System.out.println("  [ExamineResource] Closing...");
        RuntimeException closeError = new RuntimeException("Close failed");
        closeError.initCause(new RuntimeException("Underlying cause"));
        throw closeError;
    }
}

//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
  1. public static void main(String[] args)

    3public class SuppressedExceptions {4    public static void main(String[] args) {5        System.out.println("=== Suppressed Exceptions ===\n");67        // When both try body and close() throw //?both_throw8        System.out.println("--- Exception in Try Body AND close() ---");
    output=== Suppressed Exceptions ===
    --- Exception in Try Body AND close() ---
  2. this.name ← default

    pass 1 of 5
    121public ThrowingResource(String namedefault) { //?throwing_constructor122    this.name→ default = namedefault;123    System.out.println("  [" + namedefault + "] Opened"); //?print_throwing_opened124}
    output  [default] Opened
    All 5 passes — pass 1 is the card above
    passnameresourceesuppressed.lengthtr1r2r3this.name
    1default⟨ThrowingResource A⟩java.lang.RuntimeException: Error in try body1java.lang.RuntimeException: Error closing defaultdefault
    2firstfirst
    3secondsecond
    4thirdjava.lang.RuntimeException: Main error⟨ThrowingResource B⟩⟨ThrowingResource C⟩⟨ThrowingResource D⟩third
    5default⟨ThrowingResource E⟩java.lang.RuntimeException: Error closing defaultdefault
  3. try (ThrowingResource resource = new ThrowingResource())

    10try { //?try_both11    try (ThrowingResource resource⟨ThrowingResource A⟩ = new ThrowingResource()) { //?try_throwing12        resource.doWork(); //?do_work_throws13        throw new RuntimeException("Error in try body"); //?throw_body
  4. public void doWork()

    pass 1 of 2
    11            try (ThrowingResource resource = new ThrowingResource()) { //?try_throwing12                resource.doWork(); //?do_work_throws13                throw new RuntimeException("Error in try body"); //?throw_body14            }15        } catch (Exception e) { //?catch_both16            System.out.println("Primary exception: " + e.getMessage()); //?print_primary1718            Throwable[] suppressed = e.getSuppressed(); //?get_suppressed19            System.out.println("Suppressed exceptions: " + suppressed.length); //?print_suppressed_count2021            for (Throwable t : suppressed) { //?loop_suppressed22                System.out.println("  - " + t.getMessage()); //?print_suppressed23            }24        }2526        // Multiple resources, multiple close failures //?multiple_failures27        System.out.println("\n--- Multiple Resources Failing to Close ---");2829        try { //?try_multiple30            try ( //?try_multi_resources31                ThrowingResource r1 = new ThrowingResource("first"); //?first_throwing32                ThrowingResource r2 = new ThrowingResource("second"); //?second_throwing33                ThrowingResource r3 = new ThrowingResource("third") //?third_throwing34            ) {35                throw new RuntimeException("Main error"); //?main_error36            }37        } catch (Exception e) { //?catch_multiple38            System.out.println("Primary: " + e.getMessage()); //?print_multi_primary39            System.out.println("Suppressed:"); //?suppressed_header40            for (Throwable t : e.getSuppressed()) { //?loop_multi_suppressed41                System.out.println("  - " + t.getMessage()); //?print_multi_suppressed42            }43        }4445        // Only close() throws (no exception in try body) //?only_close_throws46        System.out.println("\n--- Only close() Throws ---");4748        try { //?try_only_close49            try (ThrowingResource resource = new ThrowingResource()) { //?try_throwing_only50                resource.doWork(); //?work_no_throw51                System.out.println("  Work completed successfully"); //?work_success52                // No exception here //?no_exception_comment53            }54        } catch (Exception e) { //?catch_only_close55            System.out.println("Exception from close(): " + e.getMessage()); //?print_close_exception56            System.out.println("Suppressed: " + e.getSuppressed().length); //?print_suppressed_only57        }5859        // Examining suppressed exceptions //?examine60        System.out.println("\n--- Examining Suppressed Exceptions ---");6162        try { //?try_examine63            try (ExamineResource resource = new ExamineResource()) { //?try_examine_resource64                throw new RuntimeException("Primary failure"); //?primary_failure65            }66        } catch (Exception e) { //?catch_examine67            printExceptionTree(e, 0); //?print_tree68        }6970        // Manually adding suppressed exceptions //?manual_suppress71        System.out.println("\n--- Manually Adding Suppressed ---");7273        Exception primary = new Exception("Primary error"); //?create_primary74        primary.addSuppressed(new Exception("Cleanup error 1")); //?add_suppressed175        primary.addSuppressed(new Exception("Cleanup error 2")); //?add_suppressed27677        System.out.println("Primary: " + primary.getMessage()); //?print_manual_primary78        for (Throwable t : primary.getSuppressed()) { //?loop_manual79            System.out.println("  Suppressed: " + t.getMessage()); //?print_manual_suppressed80        }8182        System.out.println("\n=== Key Points ===");83        System.out.println("""84            1. If try body throws, that's the PRIMARY exception85            2. If close() also throws, it's SUPPRESSED86            3. Access suppressed via getSuppressed()87            4. Multiple close() failures → multiple suppressed88            5. If only close() throws, that becomes the primary89            6. Suppressed exceptions preserve all error information90            """);91    }9293    static void printExceptionTree(Throwable t, int indent) { //?print_tree_method94        String prefix = "  ".repeat(indent); //?calc_prefix95        System.out.println(prefix + "Exception: " + t.getClass().getSimpleName()); //?print_type96        System.out.println(prefix + "  Message: " + t.getMessage()); //?print_message9798        Throwable[] suppressed = t.getSuppressed(); //?get_tree_suppressed99        if (suppressed.length > 0) { //?check_has_suppressed100            System.out.println(prefix + "  Suppressed:"); //?print_suppressed_header101            for (Throwable s : suppressed) { //?loop_tree102                printExceptionTree(s, indent + 2); //?recursive_call103            }104        }105106        if (t.getCause() != null) { //?check_cause107            System.out.println(prefix + "  Caused by:"); //?print_cause_header108            printExceptionTree(t.getCause(), indent + 2); //?recursive_cause109        }110    }111}112113// Resource that throws on close //?throwing_resource_class114class ThrowingResource implements AutoCloseable { //?throwing_def115    private final String name; //?throwing_name116117    public ThrowingResource() { //?throwing_constructor_default118        this("default");119    }120121    public ThrowingResource(String name) { //?throwing_constructor122        this.name = name;123        System.out.println("  [" + name + "] Opened"); //?print_throwing_opened124    }125126    public void doWork() { //?throwing_work127        System.out.println("  [" + namedefault + "] Working..."); //?print_throwing_work128    }
    output  [default] Working...
  5. @Override public void close()

    pass 1 of 5
    130@Override131public void close() { //?throwing_close132    System.out.println("  [" + namedefault + "] Closing (will throw)..."); //?print_throwing_close133    throw new RuntimeException("Error closing " + name); //?throw_close_error134}
    output  [default] Closing (will throw)...
    All 5 passes — pass 1 is the card above
    passnameesuppressed.lengtht
    1defaultjava.lang.RuntimeException: Error in try body1java.lang.RuntimeException: Error closing default
    2third
    3second
    4firstjava.lang.RuntimeException: Main error
    5defaultjava.lang.RuntimeException: Error closing default
  6. catch (Exception e)

    14    }15} catch (Exception ejava.lang.RuntimeException: Error in try body) { //?catch_both16    System.out.println("Primary exception: " + e.getMessage()); //?print_primary1718    Throwable[] suppressed = e.getSuppressed(); //?get_suppressed19    System.out.println("Suppressed exceptions: " + suppressed.length1); //?print_suppressed_count
    outputPrimary exception: Error in try body
    Suppressed exceptions: 1
  7. for (Throwable t : suppressed)

    21for (Throwable tjava.lang.RuntimeException: Error closing default : suppressed) { //?loop_suppressed22    System.out.println("  - " + t.getMessage()); //?print_suppressed23}
    output  - Error closing default
  8. System.out.println(" --- Multiple Resources Failing to Close ---");

    26// Multiple resources, multiple close failures //?multiple_failures27System.out.println("\n--- Multiple Resources Failing to Close ---");
    output
    --- Multiple Resources Failing to Close ---
  9. try ( //?try_multi_resources ThrowingResource r1 = new…

    29try { //?try_multiple30    try ( //?try_multi_resources31        ThrowingResource r1⟨ThrowingResource B⟩ = new ThrowingResource("first"); //?first_throwing32        ThrowingResource r2⟨ThrowingResource C⟩ = new ThrowingResource("second"); //?second_throwing33        ThrowingResource r3⟨ThrowingResource D⟩ = new ThrowingResource("third") //?third_throwing34    ) {35        throw new RuntimeException("Main error"); //?main_error36    }
  10. catch (Exception e)

    36    }37} catch (Exception ejava.lang.RuntimeException: Main error) { //?catch_multiple38    System.out.println("Primary: " + e.getMessage()); //?print_multi_primary39    System.out.println("Suppressed:"); //?suppressed_header40    for (Throwable t : e.getSuppressed()) { //?loop_multi_suppressed
    outputPrimary: Main error
    Suppressed:
  11. for (Throwable t : e.getSuppressed())

    pass 1 of 3
    39System.out.println("Suppressed:"); //?suppressed_header40for (Throwable tjava.lang.RuntimeException: Error closing third : e.getSuppressed()) { //?loop_multi_suppressed41    System.out.println("  - " + t.getMessage()); //?print_multi_suppressed42}
    output  - Error closing third
    All 3 passes — pass 1 is the card above
    passt
    1java.lang.RuntimeException: Error closing third
    2java.lang.RuntimeException: Error closing second
    3java.lang.RuntimeException: Error closing first
  12. System.out.println(" --- Only close() Throws ---");

    45// Only close() throws (no exception in try body) //?only_close_throws46System.out.println("\n--- Only close() Throws ---");
    output
    --- Only close() Throws ---
  13. try (ThrowingResource resource = new ThrowingResource())

    48try { //?try_only_close49    try (ThrowingResource resource⟨ThrowingResource E⟩ = new ThrowingResource()) { //?try_throwing_only50        resource.doWork(); //?work_no_throw51        System.out.println("  Work completed successfully"); //?work_success
  14. public void doWork()

    pass 2 of 2
    49            try (ThrowingResource resource = new ThrowingResource()) { //?try_throwing_only50                resource.doWork(); //?work_no_throw51                System.out.println("  Work completed successfully"); //?work_success52                // No exception here //?no_exception_comment53            }54        } catch (Exception e) { //?catch_only_close55            System.out.println("Exception from close(): " + e.getMessage()); //?print_close_exception56            System.out.println("Suppressed: " + e.getSuppressed().length); //?print_suppressed_only57        }5859        // Examining suppressed exceptions //?examine60        System.out.println("\n--- Examining Suppressed Exceptions ---");6162        try { //?try_examine63            try (ExamineResource resource = new ExamineResource()) { //?try_examine_resource64                throw new RuntimeException("Primary failure"); //?primary_failure65            }66        } catch (Exception e) { //?catch_examine67            printExceptionTree(e, 0); //?print_tree68        }6970        // Manually adding suppressed exceptions //?manual_suppress71        System.out.println("\n--- Manually Adding Suppressed ---");7273        Exception primary = new Exception("Primary error"); //?create_primary74        primary.addSuppressed(new Exception("Cleanup error 1")); //?add_suppressed175        primary.addSuppressed(new Exception("Cleanup error 2")); //?add_suppressed27677        System.out.println("Primary: " + primary.getMessage()); //?print_manual_primary78        for (Throwable t : primary.getSuppressed()) { //?loop_manual79            System.out.println("  Suppressed: " + t.getMessage()); //?print_manual_suppressed80        }8182        System.out.println("\n=== Key Points ===");83        System.out.println("""84            1. If try body throws, that's the PRIMARY exception85            2. If close() also throws, it's SUPPRESSED86            3. Access suppressed via getSuppressed()87            4. Multiple close() failures → multiple suppressed88            5. If only close() throws, that becomes the primary89            6. Suppressed exceptions preserve all error information90            """);91    }9293    static void printExceptionTree(Throwable t, int indent) { //?print_tree_method94        String prefix = "  ".repeat(indent); //?calc_prefix95        System.out.println(prefix + "Exception: " + t.getClass().getSimpleName()); //?print_type96        System.out.println(prefix + "  Message: " + t.getMessage()); //?print_message9798        Throwable[] suppressed = t.getSuppressed(); //?get_tree_suppressed99        if (suppressed.length > 0) { //?check_has_suppressed100            System.out.println(prefix + "  Suppressed:"); //?print_suppressed_header101            for (Throwable s : suppressed) { //?loop_tree102                printExceptionTree(s, indent + 2); //?recursive_call103            }104        }105106        if (t.getCause() != null) { //?check_cause107            System.out.println(prefix + "  Caused by:"); //?print_cause_header108            printExceptionTree(t.getCause(), indent + 2); //?recursive_cause109        }110    }111}112113// Resource that throws on close //?throwing_resource_class114class ThrowingResource implements AutoCloseable { //?throwing_def115    private final String name; //?throwing_name116117    public ThrowingResource() { //?throwing_constructor_default118        this("default");119    }120121    public ThrowingResource(String name) { //?throwing_constructor122        this.name = name;123        System.out.println("  [" + name + "] Opened"); //?print_throwing_opened124    }125126    public void doWork() { //?throwing_work127        System.out.println("  [" + namedefault + "] Working..."); //?print_throwing_work128    }
    output  [default] Working...
      Work completed successfully
  15. catch (Exception e)

    53    }54} catch (Exception ejava.lang.RuntimeException: Error closing default) { //?catch_only_close55    System.out.println("Exception from close(): " + e.getMessage()); //?print_close_exception56    System.out.println("Suppressed: " + e.getSuppressed().length); //?print_suppressed_only57}
    outputException from close(): Error closing default
    Suppressed: 0
  16. System.out.println(" --- Examining Suppressed Exceptions ---");

    59// Examining suppressed exceptions //?examine60System.out.println("\n--- Examining Suppressed Exceptions ---");
    output
    --- Examining Suppressed Exceptions ---
  17. public ExamineResource()

    140public ExamineResource() { //?examine_constructor141    System.out.println("  [ExamineResource] Opened"); //?print_examine_open142}
    output  [ExamineResource] Opened
  18. try (ExamineResource resource = new ExamineResource())

    62try { //?try_examine63    try (ExamineResource resource⟨ExamineResource F⟩ = new ExamineResource()) { //?try_examine_resource64        throw new RuntimeException("Primary failure"); //?primary_failure65    }
  19. closeError ← java.lang.RuntimeException: Close failed

    144@Override145public void close() { //?examine_close146    System.out.println("  [ExamineResource] Closing..."); //?print_examine_close147    RuntimeException closeError→ java.lang.RuntimeException: Close failed = new RuntimeException("Close failed"); //?create_close_error148    closeError.initCause(new RuntimeException("Underlying cause")); //?set_cause149    throw closeErrorjava.lang.RuntimeException: Close failed; //?throw_with_cause150}
    output  [ExamineResource] Closing...
  20. catch (Exception e)

    65    }66} catch (Exception ejava.lang.RuntimeException: Primary failure) { //?catch_examine67    printExceptionTree(ejava.lang.RuntimeException: Primary failure, 0); //?print_tree68}
  21. prefix ← (empty)

    pass 1 of 3
    93static void printExceptionTree(Throwable tjava.lang.RuntimeException: Primary failure, int indent0) { //?print_tree_method94    String prefix→ (empty) = "  ".repeat(indent0); //?calc_prefix95    System.out.println(prefix(empty) + "Exception: " + t.getClass().getSimpleName()); //?print_type96    System.out.println(prefix(empty) + "  Message: " + t.getMessage()); //?print_message9798    Throwable[] suppressed = t.getSuppressed(); //?get_tree_suppressed99    if (suppressed.length > 0) { //?check_has_suppressed
    outputException: RuntimeException
      Message: Primary failure
    All 3 passes — pass 1 is the card above
    passtindentsuppressed.lengthseprefixprimary
    1java.lang.RuntimeException: Primary failure01java.lang.RuntimeException: Close failed(empty)
    2java.lang.RuntimeException: Close failed2
    3java.lang.RuntimeException: Underlying cause4java.lang.RuntimeException: Close failedjava.lang.RuntimeException: Primary failure java.lang.Exception: Primary error
  22. if (suppressed.length > 0)

    98Throwable[] suppressed = t.getSuppressed(); //?get_tree_suppressed99if (suppressed.length1 > 0) { //?check_has_suppressed100    System.out.println(prefix(empty) + "  Suppressed:"); //?print_suppressed_header101    for (Throwable s : suppressed) { //?loop_tree
    output  Suppressed:
  23. for (Throwable s : suppressed)

    100System.out.println(prefix + "  Suppressed:"); //?print_suppressed_header101for (Throwable sjava.lang.RuntimeException: Close failed : suppressed) { //?loop_tree102    printExceptionTree(sjava.lang.RuntimeException: Close failed, indent0 + 2); //?recursive_call103}
  24. if (t.getCause() != null)

    106if (t.getCause() != null) { //?check_cause107    System.out.println(prefix     + "  Caused by:"); //?print_cause_header108    printExceptionTree(t.getCause(), indent2 + 2); //?recursive_cause109}
    output      Caused by:
  25. for (Throwable t : primary.getSuppressed())

    pass 1 of 2
    77System.out.println("Primary: " + primary.getMessage()); //?print_manual_primary78for (Throwable tjava.lang.Exception: Cleanup error 1 : primary.getSuppressed()) { //?loop_manual79    System.out.println("  Suppressed: " + t.getMessage()); //?print_manual_suppressed80}
    output  Suppressed: Cleanup error 1
  26. for (Throwable t : primary.getSuppressed())

    pass 2 of 2
    77System.out.println("Primary: " + primary.getMessage()); //?print_manual_primary78for (Throwable tjava.lang.Exception: Cleanup error 2 : primary.getSuppressed()) { //?loop_manual79    System.out.println("  Suppressed: " + t.getMessage()); //?print_manual_suppressed80}
    output  Suppressed: Cleanup error 2
  27. System.out.println(" === Key Points ===");

    82    System.out.println("\n=== Key Points ===");83    System.out.println("""84        1. If try body throws, that's the PRIMARY exception85        2. If close() also throws, it's SUPPRESSED86        3. Access suppressed via getSuppressed()87        4. Multiple close() failures → multiple suppressed88        5. If only close() throws, that becomes the primary89        6. Suppressed exceptions preserve all error information90        """);91}
    output
    === Key Points ===
    1. If try body throws, that's the PRIMARY exception
    2. If close() also throws, it's SUPPRESSED
    3. Access suppressed via getSuppressed()
    4. Multiple close() failures → multiple suppressed
    5. If only close() throws, that becomes the primary
    6. Suppressed exceptions preserve all error information

If close throws while handling another exception, it's "suppressed".

suppressed exception Secondary exception during cleanup. Retrieved via `getSuppressed()`.

Java 9 enhancement

Use effectively final variables.

Java9Enhancement.java
Replay: real traced execution (multi-file project)
// Java 9+ Effectively Final Variables in Try-with-Resources

public class Java9Enhancement {
    public static void main(String[] args) {
        System.out.println("=== Java 9+ Try-with-Resources Enhancement ===\n");

        // Java 7/8 style - must declare in try()
        System.out.println("--- Java 7/8 Style ---");
        java7Style();

        // Java 9+ style - can use existing effectively final variable
        System.out.println("\n--- Java 9+ Style ---");
        java9Style();

        // Multiple existing variables
        System.out.println("\n--- Multiple Existing Variables (Java 9+) ---");
        multipleExistingVariables();

        // Mixed: some new, some existing
        System.out.println("\n--- Mixed Style (Java 9+) ---");
        mixedStyle();

        // Why effectively final matters
        System.out.println("\n--- Why 'Effectively Final' Matters ---");
        whyEffectivelyFinal();

        System.out.println("\n=== Key Points ===");
        System.out.println("""
            Java 9+ Enhancement:
            1. Can use existing effectively final variables
            2. Variable must be final or effectively final
            3. Makes code cleaner when resource already exists
            4. Can mix new declarations and existing variables
            5. Useful with method parameters and factory methods
            """);
    }

    static void java7Style() {
        // Must declare in try parentheses
        try (MyResource resource = new MyResource("java7")) {
            resource.use();
        }

        // Can't do this in Java 7/8:
        // MyResource existing = new MyResource("x");
        // try (existing) { ... }  // Compile error in Java 7/8
    }

    static void java9Style() {
        // Create resource outside try
        MyResource resource = new MyResource("java9");

        // Use existing variable in try (Java 9+)
        // Just reference the variable!
        try (resource) {
            resource.use();
        }
        // resource is now closed
    }

    static void multipleExistingVariables() {
        // Create multiple resources
        MyResource r1 = new MyResource("resource1");
        MyResource r2 = new MyResource("resource2");

        // Use both in try
        // Semicolon separated
        try (r1; r2) {
            r1.use();
            r2.use();
        }
    }

    static void mixedStyle() {
        // Existing resource
        MyResource existing = new MyResource("existing");

        // Mix new declaration with existing variable
        try (
            existing; // Existing variable
            MyResource newOne = new MyResource("new") // New declaration
        ) {
            existing.use();
            newOne.use();
        }
    }

    static void whyEffectivelyFinal() {
        MyResource resource = new MyResource("demo");

        // This would make it NOT effectively final:
        // resource = new MyResource("other");  // Reassignment

        // Because 'resource' is never reassigned, it's effectively final
        try (resource) {
            resource.use();
        }

        // This WON'T compile:
        /*
        MyResource mutable = new MyResource("a");
        mutable = new MyResource("b");  // Reassignment makes it not effectively final
        try (mutable) {  // Compile error!
            mutable.use();
        }
        */
        System.out.println("  'resource' was effectively final, so it worked!");
    }

    // Useful with method parameters
    static void processResource(MyResource resource) {
        // Parameters are effectively final by default
        try (resource) {
            resource.use();
        }
    }

    // Useful with factory methods
    static void withFactory() {
        // Factory creates resource
        MyResource resource = createResource();

        // Use it in try
        try (resource) {
            resource.use();
        }
    }

    static MyResource createResource() {
        return new MyResource("from factory");
    }
}

// Resource class
class MyResource implements AutoCloseable {
    private final String name;

    public MyResource(String name) {
        this.name = name;
        System.out.println("  [" + name + "] Created");
    }

    public void use() {
        System.out.println("  [" + name + "] Being used");
    }

    @Override
    public void close() {
        System.out.println("  [" + name + "] Closed");
    }
}

//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
  1. public static void main(String[] args)

    3public class Java9Enhancement {4    public static void main(String[] args) {5        System.out.println("=== Java 9+ Try-with-Resources Enhancement ===\n");67        // Java 7/8 style - must declare in try() //?java7_style8        System.out.println("--- Java 7/8 Style ---");9        java7Style(); //?call_java7
    output=== Java 9+ Try-with-Resources Enhancement ===
    --- Java 7/8 Style ---
  2. this.name ← java7

    pass 1 of 7
    138public MyResource(String namejava7) { //?resource_constructor139    this.name→ java7 = namejava7;140    System.out.println("  [" + namejava7 + "] Created"); //?print_created141}
    output  [java7] Created
    All 7 passes — pass 1 is the card above
    passnamer1;existing;newOnethis.nameresourcer1r2existing
    1java7java7⟨MyResource A⟩
    2java9java9⟨MyResource B⟩
    3resource1resource1⟨MyResource C⟩
    4resource2⟨MyResource C⟩resource2⟨MyResource D⟩
    5existingexisting⟨MyResource E⟩
    6new⟨MyResource E⟩⟨MyResource F⟩new
    7demodemo⟨MyResource G⟩
  3. try (MyResource resource = new MyResource("java7"))

    39// Must declare in try parentheses //?must_declare40try (MyResource resource⟨MyResource A⟩ = new MyResource("java7")) { //?try_java741    resource.use(); //?use_java742}
  4. public void use()

    pass 1 of 7
    40        try (MyResource resource = new MyResource("java7")) { //?try_java741            resource.use(); //?use_java742        }4344        // Can't do this in Java 7/8: //?cant_do45        // MyResource existing = new MyResource("x");46        // try (existing) { ... }  // Compile error in Java 7/847    }4849    static void java9Style() { //?java9_method50        // Create resource outside try //?create_outside51        MyResource resource = new MyResource("java9"); //?create_resource5253        // Use existing variable in try (Java 9+) //?use_existing54        // Just reference the variable!55        try (resource) { //?try_java956            resource.use(); //?use_java957        }58        // resource is now closed //?closed_comment59    }6061    static void multipleExistingVariables() { //?multiple_method62        // Create multiple resources //?create_multiple63        MyResource r1 = new MyResource("resource1"); //?create_r164        MyResource r2 = new MyResource("resource2"); //?create_r26566        // Use both in try //?use_both67        // Semicolon separated68        try (r1; r2) { //?try_multiple69            r1.use(); //?use_r170            r2.use(); //?use_r271        }72    }7374    static void mixedStyle() { //?mixed_method75        // Existing resource //?existing_for_mixed76        MyResource existing = new MyResource("existing"); //?create_existing7778        // Mix new declaration with existing variable //?mix_declaration79        try ( //?try_mixed80            existing; // Existing variable81            MyResource newOne = new MyResource("new") // New declaration82        ) {83            existing.use(); //?use_existing_mixed84            newOne.use(); //?use_new_mixed85        }86    }8788    static void whyEffectivelyFinal() { //?why_final_method89        MyResource resource = new MyResource("demo"); //?create_demo9091        // This would make it NOT effectively final: //?not_final_comment92        // resource = new MyResource("other");  // Reassignment9394        // Because 'resource' is never reassigned, it's effectively final //?effectively_final95        try (resource) { //?try_final96            resource.use(); //?use_final97        }9899        // This WON'T compile: //?wont_compile100        /*101        MyResource mutable = new MyResource("a");102        mutable = new MyResource("b");  // Reassignment makes it not effectively final103        try (mutable) {  // Compile error!104            mutable.use();105        }106        */107        System.out.println("  'resource' was effectively final, so it worked!"); //?final_worked108    }109110    // Useful with method parameters //?method_params111    static void processResource(MyResource resource) { //?process_method112        // Parameters are effectively final by default //?params_final113        try (resource) { //?try_param114            resource.use(); //?use_param115        }116    }117118    // Useful with factory methods //?factory_methods119    static void withFactory() { //?factory_demo120        // Factory creates resource //?factory_creates121        MyResource resource = createResource(); //?call_factory122123        // Use it in try //?use_factory_result124        try (resource) { //?try_factory125            resource.use(); //?use_factory_resource126        }127    }128129    static MyResource createResource() { //?create_resource_method130        return new MyResource("from factory"); //?return_factory131    }132}133134// Resource class //?resource_class135class MyResource implements AutoCloseable { //?resource_def136    private final String name; //?resource_name137138    public MyResource(String name) { //?resource_constructor139        this.name = name;140        System.out.println("  [" + name + "] Created"); //?print_created141    }142143    public void use() { //?use_method144        System.out.println("  [" + namejava7 + "] Being used"); //?print_used145    }
    output  [java7] Being used
    All 7 passes — pass 1 is the card above
    passnameresourcer1;r2existing;newOne
    1java7⟨MyResource B⟩
    2java9⟨MyResource C⟩⟨MyResource D⟩
    3resource1
    4resource2⟨MyResource E⟩⟨MyResource F⟩
    5existing
    6new⟨MyResource G⟩
    7demo
  5. @Override public void close()

    pass 1 of 7
    8        System.out.println("--- Java 7/8 Style ---");9        java7Style(); //?call_java71011        // Java 9+ style - can use existing effectively final variable //?java9_style12        System.out.println("\n--- Java 9+ Style ---");13        java9Style(); //?call_java91415        // Multiple existing variables //?multiple_existing16        System.out.println("\n--- Multiple Existing Variables (Java 9+) ---");17        multipleExistingVariables(); //?call_multiple1819        // Mixed: some new, some existing //?mixed_style20        System.out.println("\n--- Mixed Style (Java 9+) ---");21        mixedStyle(); //?call_mixed2223        // Why effectively final matters //?why_final24        System.out.println("\n--- Why 'Effectively Final' Matters ---");25        whyEffectivelyFinal(); //?call_why_final2627        System.out.println("\n=== Key Points ===");28        System.out.println("""29            Java 9+ Enhancement:30            1. Can use existing effectively final variables31            2. Variable must be final or effectively final32            3. Makes code cleaner when resource already exists33            4. Can mix new declarations and existing variables34            5. Useful with method parameters and factory methods35            """);36    }3738    static void java7Style() { //?java7_method39        // Must declare in try parentheses //?must_declare40        try (MyResource resource = new MyResource("java7")) { //?try_java741            resource.use(); //?use_java742        }4344        // Can't do this in Java 7/8: //?cant_do45        // MyResource existing = new MyResource("x");46        // try (existing) { ... }  // Compile error in Java 7/847    }4849    static void java9Style() { //?java9_method50        // Create resource outside try //?create_outside51        MyResource resource = new MyResource("java9"); //?create_resource5253        // Use existing variable in try (Java 9+) //?use_existing54        // Just reference the variable!55        try (resource) { //?try_java956            resource.use(); //?use_java957        }58        // resource is now closed //?closed_comment59    }6061    static void multipleExistingVariables() { //?multiple_method62        // Create multiple resources //?create_multiple63        MyResource r1 = new MyResource("resource1"); //?create_r164        MyResource r2 = new MyResource("resource2"); //?create_r26566        // Use both in try //?use_both67        // Semicolon separated68        try (r1; r2) { //?try_multiple69            r1.use(); //?use_r170            r2.use(); //?use_r271        }72    }7374    static void mixedStyle() { //?mixed_method75        // Existing resource //?existing_for_mixed76        MyResource existing = new MyResource("existing"); //?create_existing7778        // Mix new declaration with existing variable //?mix_declaration79        try ( //?try_mixed80            existing; // Existing variable81            MyResource newOne = new MyResource("new") // New declaration82        ) {83            existing.use(); //?use_existing_mixed84            newOne.use(); //?use_new_mixed85        }86    }8788    static void whyEffectivelyFinal() { //?why_final_method89        MyResource resource = new MyResource("demo"); //?create_demo9091        // This would make it NOT effectively final: //?not_final_comment92        // resource = new MyResource("other");  // Reassignment9394        // Because 'resource' is never reassigned, it's effectively final //?effectively_final95        try (resource) { //?try_final96            resource.use(); //?use_final97        }9899        // This WON'T compile: //?wont_compile100        /*101        MyResource mutable = new MyResource("a");102        mutable = new MyResource("b");  // Reassignment makes it not effectively final103        try (mutable) {  // Compile error!104            mutable.use();105        }106        */107        System.out.println("  'resource' was effectively final, so it worked!"); //?final_worked108    }109110    // Useful with method parameters //?method_params111    static void processResource(MyResource resource) { //?process_method112        // Parameters are effectively final by default //?params_final113        try (resource) { //?try_param114            resource.use(); //?use_param115        }116    }117118    // Useful with factory methods //?factory_methods119    static void withFactory() { //?factory_demo120        // Factory creates resource //?factory_creates121        MyResource resource = createResource(); //?call_factory122123        // Use it in try //?use_factory_result124        try (resource) { //?try_factory125            resource.use(); //?use_factory_resource126        }127    }128129    static MyResource createResource() { //?create_resource_method130        return new MyResource("from factory"); //?return_factory131    }132}133134// Resource class //?resource_class135class MyResource implements AutoCloseable { //?resource_def136    private final String name; //?resource_name137138    public MyResource(String name) { //?resource_constructor139        this.name = name;140        System.out.println("  [" + name + "] Created"); //?print_created141    }142143    public void use() { //?use_method144        System.out.println("  [" + name + "] Being used"); //?print_used145    }146147    @Override148    public void close() { //?close_method149        System.out.println("  [" + namejava7 + "] Closed"); //?print_closed150    }
    output  [java7] Closed
    
    --- Java 9+ Style ---
    All 7 passes — pass 1 is the card above
    passnameresourcer1;r2existing;newOne
    1java7⟨MyResource B⟩
    2java9⟨MyResource C⟩⟨MyResource D⟩
    3resource2
    4resource1⟨MyResource E⟩⟨MyResource F⟩
    5new
    6existing⟨MyResource G⟩
    7demo
  6. try (resource)

    54// Just reference the variable!55try (resource⟨MyResource B⟩) { //?try_java956    resource.use(); //?use_java957}
  7. try (r1; r2)

    67// Semicolon separated68try (r1;⟨MyResource C⟩ r2⟨MyResource D⟩) { //?try_multiple69    r1.use(); //?use_r170    r2.use(); //?use_r2
  8. try ( //?try_mixed existing; // Existing variable …

    78// Mix new declaration with existing variable //?mix_declaration79try ( //?try_mixed80    existing;⟨MyResource E⟩ // Existing variable81    MyResource newOne⟨MyResource F⟩ = new MyResource("new") // New declaration82) {83    existing.use(); //?use_existing_mixed84    newOne.use(); //?use_new_mixed
  9. try (resource)

    94// Because 'resource' is never reassigned, it's effectively final //?effectively_final95try (resource⟨MyResource G⟩) { //?try_final96    resource.use(); //?use_final97}

Java 9+: existing final/effectively final variables work in try-with-resources.

Exercise: Practical.java

Build a file processor with complete resource management