Java Try-with-Resources: Automatic Resource Management

Learn how to manage resources like streams, sockets, and database connections using the Java try-with-resources statement. This feature, introduced in Java 7, simplifies resource handling by automatically closing them when the program finishes, replacing the traditional try-catch-finally pattern.



Java - Try with Resources

Introduction to Try with Resources

The Java try-with-resources statement is used for declaring one or more resources, such as streams, sockets, or database connections. These resources must be closed when the program finishes, and the try-with-resources statement ensures that resources are closed automatically at the end of the statement.

This feature was introduced in Java 7 and serves as a replacement for the traditional try-catch-finally pattern when working with resource objects. It is also known as "Automatic Resource Management." The syntax for using try-with-resources is straightforward, allowing you to declare resources within parentheses, ensuring they are closed automatically.

Syntax of Try with Resources

To utilize this statement, declare the necessary resources within parentheses. The created resources will automatically close at the end of the block. Below is the syntax for the try-with-resources statement:

Syntax

try (resources declarations) {
// Use the resources
} catch (Exception e) {
// Exception handling
}

Example: Try with Resources in Java

In the following program, we create a FileReader object within the try-with-resources statement. The FileReader fr reference is declared inside the try statement, eliminating the need to close it manually in a finally block. This helps prevent memory leaks or loose connections.

Example Code

import java.io.FileReader;
import java.io.IOException;

public class TryWithDemo {
public static void main(String[] args) {
    try (FileReader fr = new FileReader("C://example.txt")) {
        char[] a = new char[50];
        fr.read(a); // Reads content into the array
        for (char c : a) {
            System.out.print(c); // Prints characters one by one
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}
}
Output

This is an example file.

Try with Resources: Multiple Resources

You can also declare multiple resources within a single try block. Below is an example demonstrating this capability:

Example Code

// This example uses Try with Resources 
// with multiple resources
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.io.IOException;

public class Main {
public static void main(String[] args) {
    try (
        FileReader fileReader = new FileReader("C://input.txt");
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        FileWriter fileWriter = new FileWriter("C://output.txt");
        PrintWriter printWriter = new PrintWriter(fileWriter)
    ) {
        String line;
        while ((line = bufferedReader.readLine()) != null) {
            // Read content line by line and write it to the output file
            printWriter.println(line);
        }
        System.out.println("Content copied.");
    } catch (IOException e) {
        e.printStackTrace();
    }
}
}
Output

Content copied.

Example: Without Try with Resources

In the following program, we read data from a file using FileReader, manually closing it using a finally block. This approach requires us to remember to close the resource to avoid memory leaks or loose connections:

Example Code

import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class ReadDataDemo {
public static void main(String args[]) {
    FileReader fr = null;		
    try {
        File file = new File("C://file.txt");
        fr = new FileReader(file);
        char[] a = new char[50];
        fr.read(a); // Reads content into the array
        for (char c : a) {
            System.out.print(c); // Prints characters one by one
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (fr != null) {
                fr.close();
            }
        } catch (IOException ex) {		
            ex.printStackTrace();
        }
    }
}
}
Output

This is the content from the file.

Points to Remember About Try with Resources

  • Classes used with try-with-resources must implement the AutoCloseable interface, with the close() method invoked automatically at runtime.
  • You can declare multiple classes in the try-with-resources statement.
  • When multiple classes are declared, they are closed in reverse order.
  • Except for resource declarations, the syntax remains the same as a normal try/catch block.
  • Resources declared in try are instantiated just before the start of the try block.
  • Resources in the try block are implicitly declared as final.

Try with Resources: Improvements in Java 9

Before Java 9, resources had to be declared before or inside the try statement, as shown in the following example. Here, we use BufferedReader to read a string, which then needs to be closed.

Example Code (Before Java 9)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;

public class Tester {
public static void main(String[] args) throws IOException {
    System.out.println(readData("test"));
} 
static String readData(String message) throws IOException {
    Reader inputString = new StringReader(message);
    BufferedReader br = new BufferedReader(inputString);
    try (BufferedReader br1 = br) {
        return br1.readLine();
    }
}
}
Output

test

In Java 9 and later, you no longer need to declare the resource inside the try statement, as shown in the following example:

Example Code (Java 9 and Onwards)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;

public class Tester {
public static void main(String[] args) throws IOException {
    System.out.println(readData("test"));
} 
static String readData(String message) throws IOException {
    Reader inputString = new StringReader(message);
    BufferedReader br = new BufferedReader(inputString);
    try (br) {
        return br.readLine();
    }
}
}
Output

test