Java Try With Resources

Java Try With Resources was introduced in Java 7. Before Java 7 when we used a try catch block we had to ensure that any resources that we used were normally cleaned up in the finally clause. Java Try with resources removes this burden from the programmer and ensures that any resources used will be closed after execution of the block.

In order for Java Try With Resources to work the resource must implement the AutoCloseable interface.

Try With Resources Usage

For the Java Try with resources to close the resource after the block has executed, the resource must be declared and initialized inside the try.

1
2
3
try (PrintWriter writer = new PrintWriter(new File("file.txt"))) {
    writer.println("Try With Resources");
}

Replace Try Catch With Try With Resources

As an example we can use the new Java Try With Resources to replace the traditional try catch finally block. Let’s look an an example of how to replace the try catch block with the new try with resources block.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
public static void openFile_TryCatch() throws IOException {
    FileInputStream is = null;
    try {
        is = new FileInputStream(ResourceUtils.getFileFromResources("file.txt"));
        int data = is.read();
        while (data != -1) {
            System.out.print((char) data);
            data = is.read();
        }
    } finally {
        if (is != null) {
            try {
                is.close();
            } catch (IOException ioe) {
                //TODO log exception
            }
        }
    }
}

Above we have the method openFIle_TryCatch that uses a traditional try catch block. As you can see we have to explicitly write the code in the finally block to code the FileInputStream.

Now let’s improve this code by using the new Java Try With Resource construct.

1
2
3
4
5
6
7
8
9
public static void openFile_TryWithResources() throws IOException {
    try (FileInputStream is = new FileInputStream(ResourceUtils.getFileFromResources("file.txt"))) {
        int data = is.read();
        while (data != -1) {
            System.out.print((char) data);
            data = is.read();
        }
    }
}

The Java try with resources in the above removes the need to write the boilerplate code to close the FileInputStream resource.

Try With Resources Java 9 Enhancement

The Java Try With Resources before Java 9 the resource to be closed must be automatically created inside the parentheses of the try block of a try with resources construct. From Java 9 this is no longer required. If the variable referencing the resource is effectively final the reference to the resource can be placed inside the try block parentheses.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
public static void openFile_TryWithResourcesJava9() throws IOException {
    FileInputStream is = new FileInputStream(ResourceUtils.getFileFromResources("file.txt"));
    try (is) {
        int data = is.read();
        while (data != -1) {
            System.out.print((char) data);
            data = is.read();
        }
    }
}

Try With Resources With Multiple Resources

Multiple resources inside a Java try with resources block can be used and have them all automatically closed.

1
2
3
4
5
6
7
8
private static void openWriteFile_MultipleResources() throws IOException {
    try (Scanner scanner = new Scanner(ResourceUtils.getFileFromResources("file.txt"));
         PrintWriter writer = new PrintWriter(new File("fileOut.txt"))) {
        while (scanner.hasNext()) {
            writer.print(scanner.nextLine());
        }
    }
}

The resources declared in a Java try with resources construct will be closed in reverse order of the order in which they are created.

Custom AutoClosable Resource Implementations

The Java try with resources construct does not just work with Java’s built-in classes. You can create a custom resources that implements the java.lang.AutoCloseable interface in your own classes, and use them with the try with resources construct. The AutoClosable interface only has a single method called close() as can be seeing below:

1
2
3
public interface AutoClosable {
    public void close() throws Exception;
}

Any class that implements the AutoClosable interface can be used with the Java try with resources construct.

1
2
3
4
5
6
7
8
9
public class CustomAutoClosableResource implements AutoCloseable {
    public void doTask() {
        System.out.println("Task Finished");
    }
    @Override
    public void close() throws Exception {
        System.out.println("CustomAutoClosableResource closed");
    }
}

The doTask method is not part of the AutoCloseable interface we add it here as we want to do something in our example code.

1
2
3
4
5
public static void main(String[] args) throws Exception {
    try (CustomAutoClosableResource resource = new CustomAutoClosableResource()) {
        resource.doTask();
    }
}

Try With Resources Closing Order

Let’s look at an example of how the java try with resources closes resources and as we want to do something in our example code we will create three different resources to examine this.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
private static class CustomAutoClosableResource1 implements AutoCloseable {
    public CustomAutoClosableResource1() {
        System.out.println("CustomAutoClosableResource1 constructor called");
    }
    public void doTask() {
        System.out.println("CustomAutoClosableResource1 Task Finished");
    }
    @Override
    public void close() throws Exception {
        System.out.println("CustomAutoClosableResource1 closed");
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
private static class CustomAutoClosableResource2 implements AutoCloseable {
    public CustomAutoClosableResource2() {
        System.out.println("CustomAutoClosableResource2 constructor called");
    }
    public void doTask() {
        System.out.println("CustomAutoClosableResource2 Task Finished");
    }
    @Override
    public void close() throws Exception {
        System.out.println("CustomAutoClosableResource2 closed");
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
private static class CustomAutoClosableResource3 implements AutoCloseable {
    public CustomAutoClosableResource3() {
        System.out.println("CustomAutoClosableResource3 constructor called");
    }
    public void doTask() {
        System.out.println("CustomAutoClosableResource3 Task Finished");
    }
    @Override
    public void close() throws Exception {
        System.out.println("CustomAutoClosableResource3 closed");
    }
}

With the three resources created lets create the main method to test the Java Try With Resources.

1
2
3
4
5
6
7
8
9
public static void main(String[] args) throws Exception {
    try (CustomAutoClosableResource1 resource1 = new   CustomAutoClosableResource1();
         CustomAutoClosableResource2 resource2 = new CustomAutoClosableResource2();
         CustomAutoClosableResource3 resource3 = new CustomAutoClosableResource3()) {
        resource1.doTask();
        resource2.doTask();
        resource3.doTask();
    }
}

When executed the above code outputs:

1
2
3
4
5
6
7
8
9
CustomAutoClosableResource1 constructor called
CustomAutoClosableResource2 constructor called
CustomAutoClosableResource3 constructor called
CustomAutoClosableResource1 Task Finished
CustomAutoClosableResource2 Task Finished
CustomAutoClosableResource3 Task Finished
CustomAutoClosableResource3 closed
CustomAutoClosableResource2 closed
CustomAutoClosableResource1 closed

From the above output we can see that the Try With Resources closes the resources in the reverse order to which they were created.

Try With Resources Exception Handling

The exception handling of a Java try with resources block the semantics is a little bit different to the standard Java try catch finally block. If an exception is thrown from within a Java try with resources block, any resource opened inside the parentheses of the try block will still get closed automatically. As expected the throwing of an exception will force the execution to leave the try block, and this will force the automatic closing of the resource.

If a resource throws an exception when an attempt is made to close it any other resources opened within the same Java Try With Resources will automatically get closed. Once all resources are closed the exception from the failed close attempt will be propagated up the call stack as normal. It is also important to note that if multiple exceptions are thrown from multiple resources the first exception will only be propagated and the rest will be suppressed.

Moreover if an exception is thrown from inside the try with resources block, and also when a resource is closed the exception thrown from inside the try block will be propagated and the exception thrown during the close attempt will be suppressed.

Try With Resources Catch Block

A try with resources block can have catch and finally blocks which work the same as the traditional try block. A catch block can be added to a try with resources block just like you can to a standard try block. If an exception is thrown from within the body of the try block of a try with resources block, the catch block will catch it, just like it would when used with a standard try block.

1
2
3
4
5
6
try (CustomAutoClosableResource resource = new CustomAutoClosableResource()) {
    resource.doTask();
}
catch(Exception e) {
    throw new RuntimeException(e);    
}

It is important to note that before the catch block is entered, the try with resources block will attempt to close the resources opened inside the try block. If an exception is thrown while attempting to close one of the resources these exceptions can be obtained from the exceptions getSuppressed() method from inside the catch block.

1
2
3
4
5
6
7
try (CustomAutoClosableResource resource = new CustomAutoClosableResource()) {
    resource.doTask();
}
catch(Exception e) {
    Throwable[] suppressed = e.getSuppressed();
    throw e;
}

Try With Resources Finally Block

The finally block can also be used with the Java try with resources block. The finally block behaves the same as when used with the traditional try block, in that it is executed as the final step before leaving the try with resources block after any catch blocks are executed.

1
2
3
4
5
6
7
8
try (CustomAutoClosableResource resource = new CustomAutoClosableResource()) {
    resource.doTask();
} catch (Exception e) {
    Throwable[] suppressed = e.getSuppressed();
    throw e;
} finally {
    System.out.println("Finally block executed");
}

Conclusion

In this tutorial we have discussed how to use try with resources and how to replace the traditional try, catch and finally block with the newer try with resources construct. We also looked at the order in which resources are closed and the semantics of error handling.