← Back to Core Java Course | Chapter 10: Exception Handling | Lesson 8 of 8

Java try-with-resources

Try-with-resources automatically closes things like files when you are done, like a door that closes itself behind you. It replaces the manual clean-up.
Syntax
java
try (ResourceType resource = new ResourceType()) {
    // use resource; closed automatically
} catch (ExceptionType e) {
    // handle
}

The try-with-resources Syntax

Writing try (Resource r = new Resource()) inside the parentheses of a try block tells Java to manage that resource's lifecycle for you.

The resource is opened when the try block starts and is guaranteed to be closed when it ends, whether the block finishes normally or throws an exception.

Example: The try-with-resources Syntax

java
import java.io.FileWriter;
import java.io.IOException;
public class Main {
	public static void main(String[] args) throws IOException {
		try (FileWriter writer = new FileWriter("data.txt")) { // opened in the parentheses
			writer.write("Hello");
		} // closed automatically here
		System.out.println("Done");
	}
}

AutoCloseable and close()

Only objects whose class implements the AutoCloseable interface (or its subtype Closeable) can be used in a try-with-resources statement, since Java needs a close() method to call automatically.

Common examples include FileReader, BufferedReader, and JDBC's Connection and Statement classes.

Example: AutoCloseable and close()

java
// Define the class Resource
class Resource implements AutoCloseable {
	public void close() {
		// Print a line to the console
		System.out.println("Resource closed");
	}
}
// Define the class Main
public class Main {
	// Program entry point: the JVM starts running here
	public static void main(String[] args) {
		// Try code that might throw an exception
		try (Resource r = new Resource()) {
			// Print a line to the console
			System.out.println("Using resource");
		}
	}
}

Why It Replaces finally Cleanup

Before this syntax, closing a resource safely meant opening it before the try block and closing it in a finally block, which was verbose and easy to get wrong (forgetting a null check, or closing in the wrong order). try-with-resources removes that boilerplate entirely and closes resources in the reverse order they were opened.

Example: Why It Replaces finally Cleanup

java
import java.io.FileWriter;
import java.io.IOException;
public class Main {
	public static void main(String[] args) throws IOException {
		FileWriter writer = new FileWriter("data.txt");
		try {
			writer.write("Hello");
		} finally {
			writer.close(); // old, verbose, error-prone way
		}
	}
}

Multiple Resources

You can open several resources in one try-with-resources statement by separating their declarations with semicolons, for example try (FileReader fr = ...; BufferedReader br = ...).

Java closes them automatically in reverse declaration order, so the last resource opened is the first one closed.

Example: Multiple Resources

java
class Resource implements AutoCloseable {
	String name;
	Resource(String name) { this.name = name; }
	public void close() {
		System.out.println(name + " closed");
	}
}
public class Main {
	public static void main(String[] args) {
		try (Resource a = new Resource("A"); Resource b = new Resource("B")) {
			System.out.println("Using both");
		} // closed in reverse order: B then A
	}
}

Suppressed Exceptions

If the code inside the try block throws an exception and then closing the resource also throws, Java doesn't lose the second exception, it attaches it to the first as a "suppressed" exception, retrievable via getSuppressed().

This is more informative than the old finally-block pattern, where a close() failure could silently overwrite the original error.

Example: Suppressed Exceptions

java
// Define the class Resource
class Resource implements AutoCloseable {
	public void close() {
		// Throw RuntimeException to signal an error
		throw new RuntimeException("Close failed");
	}
}
// Define the class Main
public class Main {
	// Program entry point: the JVM starts running here
	public static void main(String[] args) {
		// Try code that might throw an exception
		try (Resource r = new Resource()) {
			// Throw RuntimeException to signal an error
			throw new RuntimeException("Body failed");
		// Handle RuntimeException if it was thrown
		} catch (RuntimeException e) {
			// Print a line to the console
			System.out.println(e.getMessage());
			for (Throwable suppressed : e.getSuppressed()) {
				System.out.println("Suppressed: " + suppressed.getMessage());
			}
		}
	}
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Using a variable that is not AutoCloseable in the parentheses, which is a compile error.
  2. Assuming the resource is still open after the block, when it is closed automatically.
  3. Ignoring suppressed exceptions, so a close error is lost when reading only the main exception.
Chapter Summary
  • Exceptions represent errors at run time and are handled with try-catch, including multiple catch blocks.
  • finally, throw, and throws control cleanup and how exceptions are raised or declared.
  • Custom exceptions, the exception hierarchy, and try-with-resources help you handle errors cleanly.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.