Sunday, July 31, 2011

Java 7: Try-With-Resources

The "Try With Resources", also called "Automatic Resource Management" (ARM), statement allows you to declare one or more resources in the try statement. When the statement completes, either successfully or unsuccessfully, all of its resources are closed automatically. You don't need to manually close resources in a finally block anymore, which means you don't have to worry about resource leaks.

Here is a method to make a copy of a file, using the Try-With-Resources statement. There are two resources defined in the try statement, which are automatically closed when the statement completes.

public static void copyFile(String src, String dest) throws IOException  {
  try (BufferedReader in = new BufferedReader(new FileReader(src));
       BufferedWriter out = new BufferedWriter(new FileWriter(dest))){
      String line;
      while((line = in.readLine()) != null) {
          out.write(line);
          out.write('\n');
      }
  }//no need to close resources in a "finally"
}
Here is another example, in which I have created my own resources implementing the AutoCloseable interface:
class ResourceA implements AutoCloseable{
  public void read() throws Exception{
    throw new Exception("ResourceA read exception");
  }
  @Override
  public void close() throws Exception {
    throw new Exception("ResourceA close exception");
  }
}

class ResourceB implements AutoCloseable{
  public void read() throws Exception{
    throw new Exception("ResourceB read exception");
  }
  @Override
  public void close() throws Exception {
    throw new Exception("ResourceB close exception");
  }
}

//a test method
public static void test() throws Exception{
  try (ResourceA a = new ResourceA();
       ResourceB b = new ResourceB()) {
    a.read();
    b.read();
  } catch (Exception e) {
    throw e;
  }
}
When this code is executed, a.read() throws an exception. The two resources are automatically closed, first B and then A (in the reverse order to which they were created). The "read" exception is thrown out of the method, and the two "close" exceptions are "suppressed". You can retrieve these suppressed exceptions by calling the Throwable.getSuppressed method from the exception thrown by the try block. The complete stack trace is shown below:
java.lang.Exception: ResourceA read exception
  at ResourceA.read(Dummy.java:48)
  at Dummy.test(Dummy.java:18)
  at Dummy.main(Dummy.java:38)
  Suppressed: java.lang.Exception: ResourceB close exception
    at ResourceB.close(Dummy.java:63)
    at Dummy.test(Dummy.java:20)
    ... 1 more
  Suppressed: java.lang.Exception: ResourceA close exception
    at ResourceA.close(Dummy.java:52)
    at Dummy.test(Dummy.java:20)
    ... 1 more
Further Reading:
The try-with-resources Statement

No comments:

Post a Comment