Monday, 25 May 2015

try-with-resources in Java 7

Java 7 introduced a new form of try known as try-with-resources for Automatic Resource Management (ARM). Here resource is an object that must be closed after the program is finished with it. Example of resources would be an opened file handle or database connection etc.

Note that any resource declared in a try-with-resource statement, will be closed regardless of whether the try statement completes normally or abruptly.

Apart from try-with-resources Java 7 also introduced Multi catch statement to decrease code verbosity.

General Form of try-with-resources

try-with-resources statement is a try statement that declares one or more resources with in parenthesis.

try(// resources declared here){
    // code that uses resources
} catch (ExceptionObject eObj) {
    // exception handling code
}

When using try-with-resources, finally block is not required as resources are closed automatically as soon as try-catch block is executed.

Example of try-with-resources

First let's see how it was done without try-with-resources. Before the introduction of try-with-resources we had to explicitly close the resources once the try block completes normally or abruptly . Usually, finally block of a try-catch statement was used for it.
That's how it looked like -

public class ResourceMgmtDemo {
 public static void main(String[] args) {
  BufferedReader br = null;
        try {
            br = new BufferedReader(new FileReader("C:\\test.txt"));
            System.out.println(br.readLine());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (br != null){
                 System.out.println("Closing the file");
                 br.close();
                }
                    
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }
}

Note how finally block is used here to close the file handle. We had to write one whole block just for closing the resources and there again wrap the code in try-catch block.

try-with-resources helps in reducing such boiler plate code. Let's see the same example using try-with-resources

public class ResourceMgmtDemo {
 public static void main(String[] args) {  
        try(BufferedReader br = new BufferedReader(new FileReader("C:\\test.txt"))) {            
            System.out.println(br.readLine());
        } catch (IOException e) {
            e.printStackTrace();
        } 
    }
}

It can be seen how resource is declared with the try statement itself here. Also notice the reduction in the number of lines of code!

How resources are closed automatically

Any resource that is used with try-with-resource is closed automatically because of the interface java.lang.AutoCloseable. AutoCloseable interface has a close method and any resource used with try-with-resources should implement this interface and provide implementation for the close method.

It should be noted that the close method of AutoCloseable interface throws exceptions of type Exception. Consequently, subclasses of the AutoCloseable interface can override this behavior of the close method to throw specialized exceptions.
Like in Java 7 Closeable interface extends AutoCloseable and override the behavior of close method to throw IOException. In the above example BufferedReader class is used which implements the close method of Closeable interface and throw IOException.

Using Multiple Resources

It is possible to use multiple resources inside a try-with-resources block, all of them will be closed automatically.

public class ResourceMgmtDemo {
 public static void main(String[] args) {  
        try(FileReader fr = new FileReader("C:\\test.txt");
         BufferedReader br = new BufferedReader(fr)) {            
            System.out.println(br.readLine());
        } catch (IOException e) {
            e.printStackTrace();
        } 
    }
}

This example creates two resources inside the parentheses after the try keyword. A FileReader and a BufferedReader. Note that the created resources should be separated by a semicolon. Both of these resources will be closed automatically when execution leaves the try block.
The resources will be closed in reverse order of the order in which they are listed inside the try parentheses. First BufferedReader and then the FileReader will be closed.

Suppressed Exceptions

If an exception is thrown from the try block and one or more exceptions are thrown from the try-with-resources statement, then those exceptions thrown from the try-with-resources statement are suppressed, and the exception thrown by the block is the one that is thrown in try block. You can retrieve these suppressed exceptions by calling the Throwable.getSuppressed method from the exception thrown by the try block.

This behavior is different from what will happen in case of try-catch-finally statement. If exceptions are thrown in both try block and finally block, the method returns the exception thrown in finally block.

Let's clarify the difference, with help of example code

public class ResourceMgmtDemo {
 public static void main(String[] args) {  
  try {
   normalTry();
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  try {
   tryWithResource();
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
    }
 
    private static void normalTry() throws Exception {
     MyAutoResource myAutoResource = null;
        try {
            myAutoResource = new MyAutoResource();
            System.out.println("MyAutoResource created in try block");            
            throw new Exception("Exception in try block");
        } finally {
            if (myAutoResource != null)
             myAutoResource.close();
        }
 
    }
    
    private static void tryWithResource() throws Exception {
        try (MyAutoResource myAutoResource = new MyAutoResource()) {
            System.out.println("MyAutoResource created in try-with-resources");
            throw new Exception("Exception in try-with-resources block");
        }
    }

}
// Custom implementation of AutoCoseable
class MyAutoResource implements AutoCloseable {
  
    @Override
    public void close() throws Exception {
        System.out.println("Closing MyAutoResource");
        // Here exception is thrown
        throw new Exception("Exception in Closing");
    }
}

Output

MyAutoResource created in try block
Closing MyAutoResource
java.lang.Exception: Exception in Closing
 at org.netjs.examples.impl.MyAutoResource.close(ResourceMgmtDemo.java:51)
 at org.netjs.examples.impl.ResourceMgmtDemo.normalTry(ResourceMgmtDemo.java:31)
 at org.netjs.examples.impl.ResourceMgmtDemo.main(ResourceMgmtDemo.java:10)
MyAutoResource created in try-with-resources
Closing MyAutoResource
java.lang.Exception: Exception in try-with-resources block
 at org.netjs.examples.impl.ResourceMgmtDemo.tryWithResource(ResourceMgmtDemo.java:39)
 at org.netjs.examples.impl.ResourceMgmtDemo.main(ResourceMgmtDemo.java:16)
 Suppressed: java.lang.Exception: Exception in Closing
  at org.netjs.examples.impl.MyAutoResource.close(ResourceMgmtDemo.java:51)
  at org.netjs.examples.impl.ResourceMgmtDemo.tryWithResource(ResourceMgmtDemo.java:40)
  ... 1 more

In the code we have a custom implementation of AutoCloseable called MyAutoResource with its own implementation of the close() method. Notice that an exception is thrown in the close method.

We have a method normalTry() with usual try-catch-finally block. In the try block of the method normalTry() exception is thrown. In the finally block there is a method call myAutoResource.close() which will again throw the exception in the close method of the MyAutoResource class. If you see the output the exception thrown in the finally block is displayed as that is the returned exception.

Now in the tryWithResource() method an exception is thrown because of which try-with-resources will try to close the resource and call the close method of the MyAutoResource class. In the close method again an exception is thrown. If you have see the output exception that is thrown from the try block is shown and the exception thrown from try-with-resources block is shown as Supressed exception.

Custom implementation of AutoCloseable

In the above example a custom implementation of AutoCloseable is already used. Your custom class needs to implement the AutoCloseable interface and provide implementation of the close method.

Points to note -

  • try-with-resources help in reducing the boiler plate code by providing automatic resource management.
  • With try-with-resources there is no need of having a finally block just to close the resources.
  • Any resource that is used with try-with-resource is closed automatically because of the interface java.lang.AutoCloseable.
  • Multiple resources can be opened in try-with-resources statement separated by a semicolon.
  • try-with-resources along with another feature introduced in Java 7, multi catch statement helps in reducing the number of lines in the code and increasing readability.

That's all for this topic try-with-resources. If you have any doubt or any suggestions to make please drop a comment. Thanks!



Related Topics

  1. Multi catch statement in Java 7
  2. Best practices for exception handling in Java
  3. Lambda expression and exception handling
  4. Multiple catch blocks
  5. Nested try statements
  6. Java Exception Handling interview questions

You may also like -

2 comments:

  1. This post gives me enough information on what is try-with-resources Feature.........
    Thank you so much can you please make post on Class class in Java with simple example.

    ReplyDelete
    Replies
    1. Glad that I could be of any help!
      You can have a look at this post Reflection in Java - Class to get information about Class class in Java.

      Delete