Java 7: try-with-resources explained

This article examines the use of the try-with-resources statement. This is a try statement that declares one or more resources. A resource is as an object that must be closed after the program is finished with it.

The try-with-resources statement ensures that each resource is closed at the end of the statement. Any object that implements the java.lang.AutoCloseable or java.io.Closeable interface can be used as a resource.

Prior to try-with-resources (before Java 7) while dealing with SQL Statement or ResultSet or Connection objects or other IO objects one had to explicitly close the resource. So one would write something like:

try{
  //Create a resource- R
} catch(SomeException e){
  //Handle the exception
} finally{
  //if resource R is not null then
  try{
    //close the resource
  }
  catch(SomeOtherException ex){
  }
}

We have to explicitly close the resource and thereby add a few more lines of code. There are few cases where the developer will forget to close the resource. So to overcome these and other issues – try-with-resources is introduced in Java 7.

Lets look at an example of how we would use try..catch…finally in pre Java 7. Let me create 2 custom exceptions – ExceptionA and ExceptionB. These will be used through out the examples.

public class ExceptionA extends Exception{
    public ExceptionA(String message){
        super(message);
    }
}
public class ExceptionB extends Exception{
    public ExceptionB(String message){
        super(message);
    }
}

Lets create some resource, say OldResource, which has two methods – doSomeWork(): which does some work and close(): which does the closing. Note that this depicts the use of a generic resource – do some work and then close the resource. Now each of these operations, doSomeWork and close, throws an exception.

public class OldResource{
    public void doSomeWork(String work) throws ExceptionA{
        System.out.println("Doing: "+work);
        throw new ExceptionA("Exception occured while doing work");
    }
    public void close() throws ExceptionB{
        System.out.println("Closing the resource");
        throw new ExceptionB("Exception occured while closing");
    }
}

Lets use this resource in a sample program:

public class OldTry {
    public static void main(String[] args) {
        OldResource res = null;
        try {
            res = new OldResource();
            res.doSomeWork("Writing an article");
        } catch (Exception e) {
            System.out.println("Exception Message: "+
                      e.getMessage()+" Exception Type: "+e.getClass().getName());
        } finally{
            try {
                res.close();
            } catch (Exception e) {
                System.out.println("Exception Message: "+
                         e.getMessage()+" Exception Type: "+e.getClass().getName());
            }
        }
    }
}

The output:

Doing: Writing an article
Exception Message: Exception occured while doing work Exception Type: javaapplication4.ExceptionA
Closing the resource
Exception Message: Exception occured while closing Exception Type: javaapplication4.ExceptionB

The program is straight forward: create a new resource, use it, and then try to close it. One can look at the number of extra lines of code there.

Now lets implement the same program using Java 7?s try-with-resource construct. For this we would need a new resource – NewResource. In Java 7 a new interface has been, java.lang.AutoCloseable. Those resources which need to be closed implement this interface. All the older IO APIs, socket APIs etc. implement the Closeable interface – which means these resources can be closed. With Java 7, java.io.Closeable implements AutoCloseable. So everything works without breaking any existing code.

The NewResource code below:

public class NewResource implements AutoCloseable{
    String closingMessage;
 
    public NewResource(String closingMessage) {
        this.closingMessage = closingMessage;
    }
 
    public void doSomeWork(String work) throws ExceptionA{
        System.out.println(work);
        throw new ExceptionA("Exception thrown while doing some work");
    }
    public void close() throws ExceptionB{
        System.out.println(closingMessage);
        throw new ExceptionB("Exception thrown while closing");
    }
 
    public void doSomeWork(NewResource res) throws ExceptionA{
        res.doSomeWork("Wow res getting res to do work");
    }
}

Now lets use the NewResource in a sample Program using try-with-resource:

public class TryWithRes {
    public static void main(String[] args) {
        try(NewResource res = new NewResource("Res1 closing")){
            res.doSomeWork("Listening to podcast");
        } catch(Exception e){
            System.out.println("Exception: "+
       e.getMessage()+" Thrown by: "+e.getClass().getSimpleName());
        }
    }
}

The output:

Listening to podcast
Res1 closing
Exception: Exception thrown while doing some work Thrown by: ExceptionA

One thing to note above is that the Exception thrown by the close is being suppressed by the Exception being thrown by the worker method.

So you can right away notice the difference between the two implementations, one using try…catch…finally and the other using try-with-resource. In the example above only one resource is declared as used. One can declare and use multiple resources within the try block, also nest these try-with-resources blocks.

Along with this, a few new methods and a constructor were added to the java.lang.Throwable class, all related to suppressing the exceptions thrown along with other exception. Best example for this would be- ExceptionA being thrown by the try block will get suppressed by the ExceptionB being thrown by the finally (while closing the resource) and this was the behavior pre Java 7.

However, with Java 7, the thrown exception keeps track of the exceptions it suppressed on its way to being caught/handled. So the earlier said example can be restated as follows. The ExceptionB being thrown by the close method gets added to the List of suppressed exception of the ExceptionA which is being thrown by the try block.

Let me explain you nested try-with-resources and Suppressed exceptions with the following examples.

Nested try-with-resources

public class TryWithRes {
    public static void main(String[] args) {
        try(NewResource res = new NewResource("Res1 closing");
            NewResource res2 = new NewResource("Res2 closing")){
            try(NewResource nestedRes = new NewResource("Nestedres closing")){
                nestedRes.doSomeWork(res2);
            }
        } catch(Exception e){
            System.out.println("Exception: "+
      e.getMessage()+" Thrown by: "+e.getClass().getSimpleName());
        }
 
    }
}

The output for the above would be:

Wow res getting res to do work
Nestedres closing
Res2 closing
Res1 closing
Exception: Exception thrown while doing some work Thrown by: ExceptionA

Note the order of closing the resources, latest first. Also note that the exception being thrown by each of these close() operations is suppressed.

Lets see how we can retrieve the suppressed exceptions:

Suppressed Exceptions

public class TryWithRes {
    public static void main(String[] args) {
        try(NewResource res = new NewResource("Res1 closing");
            NewResource res2 = new NewResource("Res2 closing")){
            try(NewResource nestedRes = new NewResource("Nestedres closing")){
                nestedRes.doSomeWork(res2);
            }
        } catch(Exception e){
            System.out.println("Exception: "+
      e.getMessage()+" Thrown by: "+e.getClass().getSimpleName());
            if (e.getSuppressed() != null){
                for (Throwable t : e.getSuppressed()){
                    System.out.println(t.getMessage()+
                               " Class: "+t.getClass().getSimpleName());
                }
            }
        }
 
    }
}

The output for the above code:

Wow res getting res to do work
Nestedres closing
Res2 closing
Res1 closing
Exception: Exception thrown while doing some work Thrown by: ExceptionA
Exception thrown while closing Class: ExceptionB
Exception thrown while closing Class: ExceptionB
Exception thrown while closing Class: ExceptionB

The getSuppressed() method is used to retrieve the exceptions supressed by the thrown exception. Also a new constructor has been added to Throwable class which can be used to enable or disable the suppression of exceptions. If disabled none of the suppressed exceptions are tracked.

Reference: Java 7 Project Coin: try-with-resources explained with examples from our JCG partner Mohamed Sanaulla at the Experiences Unlimited blog.

Related Articles :
Related Whitepaper:

Bulletproof Java Code: A Practical Strategy for Developing Functional, Reliable, and Secure Java Code

Use Java? If you do, you know that Java software can be used to drive application logic of Web services or Web applications. Perhaps you use it for desktop applications? Or, embedded devices? Whatever your use of Java code, functional errors are the enemy!

To combat this enemy, your team might already perform functional testing. Even so, you're taking significant risks if you have not yet implemented a comprehensive team-wide quality management strategy. Such a strategy alleviates reliability, security, and performance problems to ensure that your code is free of functionality errors.Read this article to learn about this simple four-step strategy that is proven to make Java code more reliable, more secure, and easier to maintain.

Get it Now!  

5 Responses to "Java 7: try-with-resources explained"

  1. Alejandro Hdez. Angeles says:

    Excellent tutorial

  2. Excellent Article on try with resources

  3. Ronak Patel says:

    Nice writeup, easy to understand.
    Keep posting.

  4. @All Thanks a lot for reading the tutorial.

  5. Kevin says:

    Nicely done. Thank you!

Leave a Reply


three × = 24



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.

Sign up for our Newsletter

20,709 insiders are already enjoying weekly updates and complimentary whitepapers! Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

As an extra bonus, by joining you will get our brand new e-books, published by Java Code Geeks and their JCG partners for your reading pleasure! Enter your info and stay on top of things,

  • Fresh trends
  • Cases and examples
  • Research and insights
  • Two complimentary e-books