Image of Java try-with-resources

ADVERTISEMENT

Introduction

Java 7 supports a new statement called try-with-resources which extends the behavior of the traditional try/catch block for the sake of automatic resource management, since Java 7 developers are able to access resources (files, db connections, sockets) inside a try-with-resources block without the need to worry about closing them afterwards, the resource closure is done automatically.

1. Resource management using traditional try/catch

Before Java 7, the traditional way of accessing a resource in a java application is through surrounding it with a try/catch block and closing it manually in a finally block as the following:

try
{
    // access resources here
} 
catch (FileNotFoundException e) 
{
    // Exception handling
}
finally
{
    // close resources
}

This approach used to cause memory leaks and resource exhaustion in case developers forget to close the used resources in a finally block.

2. Resource management using try-with-resources

Java 7 introduced a new resource management approach called try-with-resources which closes the resources automatically after usage. Following is the structure of the try-with-resources statement:

try(/* open resources here*/)
{
    // access resources here
} 
catch (FileNotFoundException e) 
{
    // exception handling
}
// resources are closed as soon as try-catch block is executed.

P.S: It is worth to mention that in order for the resource to be auto managed by try-with-resources, it should extend AutoCloseable class, here is a list of all auto close-able classes.

3. Read file from file system

Following is a practical comparison between try/catch/finally and try-with-resources approaches for reading and displaying the content of a file in a file system.

using try/catch/finally

public void readFileUsingTraditionalTryCatch()
    {
        InputStream input = null;
        try 
        {
            input = new FileInputStream(new File("test.pdf"));
            int content;
            while ((content = input.read()) != -1) {
                System.out.print((char) content);
            }
        } 
        catch (FileNotFoundException fileNotFoundException) 
        {
            // File is not found
            fileNotFoundException.printStackTrace();
        }
        catch (IOException ioException)
        {
            // error while reading file
            ioException.printStackTrace();
        }
        finally
        {
            // this is to prevent NullPointerException in case 
            // exception occurs while opening file
            if(input != null)
            {
                try {
                    input.close();
                } catch (IOException e) {
                    // Handle exception again when closing the input stream
                    e.printStackTrace();
                }
            }
        }
    }

As you notice, too much manual interaction and handling in the above approach:

  • Developer should manually close the InputStream in a finally block.
  • When closing the InputStream, it’s possible that the close() method throws exception, then developer should keep handling the failure of closing in an infinite try/catch/finally blocks. using try-with-resources

The above problems are automatically handled when using try-with-resources statement, below is how we read and display file contents in Java 7:

public void readFileUsingTryWithResource()
{
    try(InputStream input = new FileInputStream(new File("test.pdf")))
    {
        int content;
        while ((content = input.read()) != -1) {
            System.out.print((char) content);
        }
    }
    catch(IOException ioException)
    {
        // error while reading file
        ioException.printStackTrace();
    }
        
    // stream is automatically closed here.
}

4. Advantages of try-with-resources

Below are the main benefits of preferring try-with-resources over the traditional try/catch block:

  1. Resources are closed automatically after usage without the need for developer interaction.
  2. In the traditional try/catch block, the exceptions which occur in the finally block override the exceptions which occur in the try block, hence only finally block exceptions are propagated. However, in try-with-resources, exceptions thrown when closing resources are suppressed and the exception thrown in the try block is considered.
  3. Try-with-resources reduces the boiler plate code and makes your code look shorter and more readable.

5. Common points on try-with-resources

Following are common points to consider when using try-with-resources:

  1. Only AutoCloseable resources can be defined in the try() statement.
  2. The scope of the resources defined in the try() statement is only limited to the try-with-resources block and can’t be used outside it.
public void readFileUsingTryWithResource()
{
    try(InputStream input = new FileInputStream(new File("test.pdf")))
    {
    }
    catch(IOException ioException)
    {
    }
        
    // input variable cannot be accessed here
}
  1. Multiple resources can be defined in the try() statement, and the close methods of resources are automatically called in the opposite order of their creation.
try (BufferedReader br = new BufferedReader(new FileReader("test.pdf"));
    java.io.BufferedWriter writer = java.nio.file.Files.newBufferedWriter(
    FileSystems.getDefault().getPath("test1.pdf"), Charset.defaultCharset())) 
{
    System.out.println(br.readLine());
            
} catch (IOException e) {
    e.printStackTrace();
}

here writer.close() is implicitly called before br.close().

  1. Catch and finally blocks can still be used in a try-with-resources statement, they are run after the resources declared have been closed.
  2. Try-with-resources only close the resources defined in the try() statement, it doesn’t close the resources defined afterwards inside the try block.
  3. Exceptions thrown while implicitly closing the resources are suppressed and only exceptions which occur in the try block are propagated.

Summary

Java 7 supports a new statement called try-with-resources which extends the behavior of the traditional try/catch block for the sake of automatic resource management, since Java 7 developers are able to access resources (files, db connections, sockets) inside a try-with-resources block without the need to worry about closing them afterwards, the resource closure is done automatically.

Next Steps

If you're interested in learning more about the basics of Java, coding, and software development, check out our Coding Essentials Guidebook for Developers, where we cover the essential languages, concepts, and tools that you'll need to become a professional developer.

Thanks and happy coding! We hope you enjoyed this article. If you have any questions or comments, feel free to reach out to jacob@initialcommit.io.