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 having 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 resource 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 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 the BufferedReader will be closed, then the FileReader.

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

Note that from the try-with-resources block exception that is thrown from the try block is shown but it also shows the exception thrown from try-with-resources block as Supressed exception.

Also note that here a custom implementation of AutoCloseable interface is used with try-with-resource.

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. Exception handling and method overriding
  2. Multiple catch blocks
  3. Nested try statements
  4. Multi catch statement in Java 7
  5. Best practices for exception handling in Java
  6. Lambda expression and exception handling
  7. 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