Exceptions
Try-with-Resources
Automatic Cleanup
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.
// 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");
}
}
}
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
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 ---this.name ← myResource
pass 1 of 474public SimpleResource(String namemyResource) { //?constructor75 this.name→ myResource = namemyResource; //?set_name76 System.out.println(" [" + namemyResource + "] Resource opened"); //?print_opened77}output [myResource] Resource openedAll 4 passes — pass 1 is the card above pass nametriggerErrorethis.nameresource1 myResource — — myResource ⟨SimpleResource A⟩ 2 errorResource true java.lang.RuntimeException: Something went wrong! errorResource ⟨SimpleResource B⟩ 3 finallyResource — — finallyResource ⟨SimpleResource C⟩ 4 oldStyle — — oldStyle ⟨SimpleResource D⟩ 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_completedpublic void doWork()
pass 1 of 410 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 completedAll 4 passes — pass 1 is the card above pass nameresourcetriggerErrore1 myResource ⟨SimpleResource B⟩ — — 2 errorResource — true java.lang.RuntimeException: Something went wrong! 3 finallyResource — — — 4 oldStyle ⟨SimpleResource D⟩ — — @Override //?override_close public void close()
pass 1 of 488@Override //?override_close89public void close() { //?close_method90 if (!closed) { //?if_not_closedAll 4 passes — pass 1 is the card above pass resourcetriggerErrore1 ⟨SimpleResource B⟩ true — 2 — — java.lang.RuntimeException: Something went wrong! 3 — — — 4 — — — closed ← true, triggerError ← true
pass 1 of 415 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 pass nameresourceeclosedtriggerError1 myResource ⟨SimpleResource B⟩ — false → true true 2 errorResource — java.lang.RuntimeException: Something went wrong! false → true — 3 finallyResource — — false → true — 4 oldStyle — — false → true — 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_errorif (triggerError)
22resource.doWork(); //?do_work_catch23if (triggerErrortrue) { //?check_trigger_error24 resource.causeError(); //?cause_error25}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!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 ---try (SimpleResource resource = new SimpleResource("finallyResource"))
35try (SimpleResource resource⟨SimpleResource C⟩ = new SimpleResource("finallyResource")) { //?try_finally36 resource.doWork(); //?do_work_finally37} finally { //?finally_block36 resource.doWork(); //?do_work_finally37} finally { //?finally_block38 System.out.println("Finally block runs AFTER close()"); //?finally_message39}outputFinally block runs AFTER close()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_styleoutput --- Old Style (Don't Do This) ---resource ← null
56static void oldStyleExample() { //?old_style_method57 SimpleResource resource→ null = null; //?init_null58 try { //?old_tryif (resource != null)
61} finally { //?old_finally62 if (resource⟨SimpleResource D⟩ != null) { //?null_check63 resource.close(); //?manual_close64 }
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 ---this.name ← myResource
pass 1 of 474public SimpleResource(String namemyResource) {75 this.name→ myResource = namemyResource;76 System.out.println(" [" + namemyResource + "] Resource opened");77}output [myResource] Resource openedAll 4 passes — pass 1 is the card above pass namethis.nameresource1 myResource myResource ⟨SimpleResource A⟩ 2 errorResource errorResource ⟨SimpleResource B⟩ 3 finallyResource finallyResource ⟨SimpleResource C⟩ 4 oldStyle oldStyle ⟨SimpleResource D⟩ try (SimpleResource resource = new SimpleResource("myResource"))
10try (SimpleResource resource⟨SimpleResource A⟩ = new SimpleResource("myResource")) {11 resource.doWork();12 System.out.println("Work completed");public void doWork()
pass 1 of 410 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 completedAll 4 passes — pass 1 is the card above pass nameresource1 myResource ⟨SimpleResource B⟩ 2 errorResource ⟨SimpleResource C⟩ 3 finallyResource — 4 oldStyle ⟨SimpleResource D⟩ @Override public void close()
pass 1 of 488@Override89public void close() {90 if (!closed) {All 4 passes — pass 1 is the card above pass resource1 ⟨SimpleResource B⟩ 2 ⟨SimpleResource C⟩ 3 — 4 — closed ← true, triggerError ← false
pass 1 of 415 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 pass nameresourceclosedtriggerError1 myResource ⟨SimpleResource B⟩ false → true false 2 errorResource ⟨SimpleResource C⟩ false → true — 3 finallyResource — false → true — 4 oldStyle — false → true — try (SimpleResource resource = new SimpleResource("errorResource"))
20boolean triggerError = false;21try (SimpleResource resource⟨SimpleResource B⟩ = new SimpleResource("errorResource")) {22 resource.doWork();23 if (triggerError) {try (SimpleResource resource = new SimpleResource("finallyResource"))
35try (SimpleResource resource⟨SimpleResource C⟩ = new SimpleResource("finallyResource")) {36 resource.doWork();37} finally {36 resource.doWork();37} finally {38 System.out.println("Finally block runs AFTER close()");39}outputFinally block runs AFTER close()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) ---resource ← null
56static void oldStyleExample() {57 SimpleResource resource→ null = null;58 try {if (resource != null)
61} finally {62 if (resource⟨SimpleResource D⟩ != null) {63 resource.close();64 }
try (Resource r = new Resource()) { } - automatically closed after block.
Multiple resources
Manage several resources at once.
// 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);
}
}
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
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) ---this.name ← first
pass 1 of 883public Resource(String namefirst) { //?resource_constructor84 this.name→ first = namefirst;85 System.out.println(" → Opening: " + namefirst); //?print_opening86}output → Opening: firstAll 8 passes — pass 1 is the card above pass namer1r2r3outerethis.namethis.outer1 first — — — — — first — 2 second — — — — — second — 3 third ⟨Resource A⟩ ⟨Resource B⟩ ⟨Resource C⟩ ⟨OuterResource D⟩ — third ⟨OuterResource D⟩ 4 good1 — — — — — good1 — 5 failing — — — — java.lang.RuntimeException: Failed to open: failing failing — 6 A — — — — — A — 7 B — — — — — B — 8 C ⟨Resource E⟩ ⟨Resource F⟩ ⟨Resource G⟩ — java.lang.RuntimeException: Error during processing C — 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_r2outputUsing all resources...public void use()
pass 1 of 415 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: firstAll 4 passes — pass 1 is the card above pass nameouterethis.namethis.outer1 first — — — — 2 second — — — — 3 third ⟨OuterResource D⟩ — outer ⟨OuterResource D⟩ 4 A — java.lang.RuntimeException: Error during processing — — @Override public void close()
pass 1 of 792@Override93public void close() { //?close_resource94 System.out.println(" ← Closing: " + namethird); //?print_closing95}output ← Closing: thirdAll 7 passes — pass 1 is the card above pass nameouterethis.namethis.outer1 third — — — — 2 second — — — — 3 first ⟨OuterResource D⟩ — outer ⟨OuterResource D⟩ 4 good1 — java.lang.RuntimeException: Failed to open: failing — — 5 C — — — — 6 B — — — — 7 A — java.lang.RuntimeException: Error during processing — — 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: outerthis.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}public String getData()
pass 1 of 2115public String getData() { //?get_data116 return "data from " + nameouter; //?return_data117}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)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}public String getData()
pass 2 of 2115public String getData() { //?get_data116 return "data from " + nameouter; //?return_data117}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@Override public void close()
140@Override141public void close() { //?close_inner142 System.out.println(" ← Closing inner: " + nameinner); //?print_inner_close143}output ← Closing inner: inner@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 ---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 }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: failingSystem.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 ---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_duringcatch (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 processingSystem.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.
// 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();
}
}
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
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 ---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: operationtry (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"); //?completedelapsedMs ← 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@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 ---try (Counter counter = new Counter())
18try (Counter counter⟨Counter B⟩ = new Counter()) { //?try_counter19 counter.increment(); //?inc120 counter.increment(); //?inc2count ← 1
pass 1 of 418 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_closedAll 4 passes — pass 1 is the card above pass count1 0 → 1 2 1 → 2 3 2 → 3 4 3 System.out.println(" Count: " + counter.getCount()); //?print_count
21 counter.increment(); //?inc322 System.out.println(" Count: " + counter.getCount()); //?print_count23}output Count: 3closed ← 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 ---try (SafeResource resource = new SafeResource())
28try (SafeResource resource⟨SafeResource C⟩ = new SafeResource()) { //?try_safe29 resource.process(); //?process_safe30}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...@Override public void close()
118@Override119public void close() { //?safe_close120 System.out.println(" [SafeResource] Closing..."); //?print_closing121 try { //?try_cleanupoutput [SafeResource] Closing...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 ---try (IdempotentResource resource = new IdempotentResource())
35try (IdempotentResource resource⟨IdempotentResource D⟩ = new IdempotentResource()) { //?try_idempotent36 resource.use(); //?use_idempotent37 resource.close(); //?manual_closepublic 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 resourcecloseCallCount ← 1
pass 1 of 3147@Override148public void close() { //?idempotent_close149 closeCallCount→ 1++; //?increment_count150 System.out.println(" [Idempotent] close() called (call #" + closeCallCount1 + ")"); //?print_calloutput [Idempotent] close() called (call #1)All 3 passes — pass 1 is the card above pass cleanupActionresourcecloseCallCountclosedthis.cleanupAction1 — — 0 → 1 false → true — 2 — — 1 → 2 — — 3 ⟨CustomAutocloseable lambda E⟩ ⟨CallbackResource F⟩ 2 → 3 — ⟨CustomAutocloseable lambda E⟩ 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 resourceselse
pass 1 of 237 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 nothingelse
pass 2 of 242 // 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 ---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 createdtry (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}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...@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.
Suppressed exceptions
Handle exceptions during close.
// 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;
}
}
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
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() ---this.name ← default
pass 1 of 5121public ThrowingResource(String namedefault) { //?throwing_constructor122 this.name→ default = namedefault;123 System.out.println(" [" + namedefault + "] Opened"); //?print_throwing_opened124}output [default] OpenedAll 5 passes — pass 1 is the card above pass nameresourceesuppressed.lengthtr1r2r3this.name1 default ⟨ThrowingResource A⟩ java.lang.RuntimeException: Error in try body 1 java.lang.RuntimeException: Error closing default — — — default 2 first — — — — — — — first 3 second — — — — — — — second 4 third — java.lang.RuntimeException: Main error — — ⟨ThrowingResource B⟩ ⟨ThrowingResource C⟩ ⟨ThrowingResource D⟩ third 5 default ⟨ThrowingResource E⟩ java.lang.RuntimeException: Error closing default — — — — — default 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_bodypublic void doWork()
pass 1 of 211 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...@Override public void close()
pass 1 of 5130@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 pass nameesuppressed.lengtht1 default java.lang.RuntimeException: Error in try body 1 java.lang.RuntimeException: Error closing default 2 third — — — 3 second — — — 4 first java.lang.RuntimeException: Main error — — 5 default java.lang.RuntimeException: Error closing default — — 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_countoutputPrimary exception: Error in try body Suppressed exceptions: 1for (Throwable t : suppressed)
21for (Throwable tjava.lang.RuntimeException: Error closing default : suppressed) { //?loop_suppressed22 System.out.println(" - " + t.getMessage()); //?print_suppressed23}output - Error closing defaultSystem.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 ---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 }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_suppressedoutputPrimary: Main error Suppressed:for (Throwable t : e.getSuppressed())
pass 1 of 339System.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 thirdAll 3 passes — pass 1 is the card above pass t1 java.lang.RuntimeException: Error closing third 2 java.lang.RuntimeException: Error closing second 3 java.lang.RuntimeException: Error closing first 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 ---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_successpublic void doWork()
pass 2 of 249 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 successfullycatch (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: 0System.out.println(" --- Examining Suppressed Exceptions ---");
59// Examining suppressed exceptions //?examine60System.out.println("\n--- Examining Suppressed Exceptions ---");output --- Examining Suppressed Exceptions ---public ExamineResource()
140public ExamineResource() { //?examine_constructor141 System.out.println(" [ExamineResource] Opened"); //?print_examine_open142}output [ExamineResource] Openedtry (ExamineResource resource = new ExamineResource())
62try { //?try_examine63 try (ExamineResource resource⟨ExamineResource F⟩ = new ExamineResource()) { //?try_examine_resource64 throw new RuntimeException("Primary failure"); //?primary_failure65 }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...catch (Exception e)
65 }66} catch (Exception ejava.lang.RuntimeException: Primary failure) { //?catch_examine67 printExceptionTree(ejava.lang.RuntimeException: Primary failure, 0); //?print_tree68}prefix ← (empty)
pass 1 of 393static 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_suppressedoutputException: RuntimeException Message: Primary failureAll 3 passes — pass 1 is the card above pass tindentsuppressed.lengthseprefixprimary1 java.lang.RuntimeException: Primary failure 0 1 java.lang.RuntimeException: Close failed — (empty) — 2 java.lang.RuntimeException: Close failed 2 — — — — 3 java.lang.RuntimeException: Underlying cause 4 — java.lang.RuntimeException: Close failed java.lang.RuntimeException: Primary failure java.lang.Exception: Primary error 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_treeoutput Suppressed: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}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:for (Throwable t : primary.getSuppressed())
pass 1 of 277System.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 1for (Throwable t : primary.getSuppressed())
pass 2 of 277System.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 2System.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".
Java 9 enhancement
Use effectively final variables.
// 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");
}
}
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
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_java7output=== Java 9+ Try-with-Resources Enhancement === --- Java 7/8 Style ---this.name ← java7
pass 1 of 7138public MyResource(String namejava7) { //?resource_constructor139 this.name→ java7 = namejava7;140 System.out.println(" [" + namejava7 + "] Created"); //?print_created141}output [java7] CreatedAll 7 passes — pass 1 is the card above pass namer1;existing;newOnethis.nameresourcer1r2existing1 java7 — — — java7 ⟨MyResource A⟩ — — — 2 java9 — — — java9 ⟨MyResource B⟩ — — — 3 resource1 — — — resource1 — ⟨MyResource C⟩ — — 4 resource2 ⟨MyResource C⟩ — — resource2 — — ⟨MyResource D⟩ — 5 existing — — — existing — — — ⟨MyResource E⟩ 6 new — ⟨MyResource E⟩ ⟨MyResource F⟩ new — — — — 7 demo — — — demo ⟨MyResource G⟩ — — — 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}public void use()
pass 1 of 740 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 usedAll 7 passes — pass 1 is the card above pass nameresourcer1;r2existing;newOne1 java7 ⟨MyResource B⟩ — — — — 2 java9 — ⟨MyResource C⟩ ⟨MyResource D⟩ — — 3 resource1 — — — — — 4 resource2 — — — ⟨MyResource E⟩ ⟨MyResource F⟩ 5 existing — — — — — 6 new ⟨MyResource G⟩ — — — — 7 demo — — — — — @Override public void close()
pass 1 of 78 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 pass nameresourcer1;r2existing;newOne1 java7 ⟨MyResource B⟩ — — — — 2 java9 — ⟨MyResource C⟩ ⟨MyResource D⟩ — — 3 resource2 — — — — — 4 resource1 — — — ⟨MyResource E⟩ ⟨MyResource F⟩ 5 new — — — — — 6 existing ⟨MyResource G⟩ — — — — 7 demo — — — — — try (resource)
54// Just reference the variable!55try (resource⟨MyResource B⟩) { //?try_java956 resource.use(); //?use_java957}try (r1; r2)
67// Semicolon separated68try (r1;⟨MyResource C⟩ r2⟨MyResource D⟩) { //?try_multiple69 r1.use(); //?use_r170 r2.use(); //?use_r2try ( //?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_mixedtry (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