Archive for September, 2011

Try-with-resources in JDK7 without scoped declarations

26 September 2011

A handy new feature in JDK7 is the try-with-resources statement. This statement is meant to eliminate a lot of the boilerplate code required for managing InputStreams and OutputStreams. Say for example, that I would want to copy the contents of an InputStream to an OutputStream. This would require the following code only to manage the in- and output stream:

InputStream in = createInputStream();
try {
   OutputStream out = createOutputStream();
   try {
      /* Copy data here */
   } finally {
      try {
         out.close();
      } catch(IOException e) {
         //Prevent this exception from suppressing actual exception
      }
   }
} finally {
   try {
      in.close();
   } catch(IOException e) {
      //Prevent this exception from suppressing actual exception
   }
}

Using the new try-with-resources statement, the above code can be rewritten as the following:

try (InputStream in = createInputStream(); OutputStream out = 
      createOutputStream()) {
   /* Copy data here */
}

The InputStream and OutputStream are automatically closed at the end of the try-with-resources block. If an exception is thrown during the main block and then again during the closing of one (or both) of the streams, the exception on the close operation is added to the original exception as a suppressed exception, so no exceptions are swallowed silently anymore. The try-with-resources blocks are also not limited to be used for in- and output streams, but can be used on any object that implements the AutoCloseable interface.

There is one minor disadvantage to the try-with-resource statement, it is required to define the variable that refers to the object to be closed within the brackets after the try. For example, if you have a method that receives an InputStream as a parameter, the Java compiler would not allow you to do this:

public void readData(InputStream in) {
   try(in) {
      int input;
      while((input = in.read()) >=0) {
         //Use input here
      }
   }
}

The above code would produce a compiler error as no variable has been defined between the brackets of the try-with-resources statement. I would propose the following workaround for this situation:

public void readData(InputStream in) {
   try(InputStream autoCloseableInputStream = in) {
      int input;
      while((input = in.read()) >=0) {
         //Use input here
      }
   }
}

 


This code does compile and the stream is automatically closed at the end of the try block. Since the autoCloseableInputStream and in variables refer to the exact same object, it is not necessary to actually use the autoCloseableInputStream variable in the code. Using a name like autoCloseableInputStream makes it clear that this variable is only defined in order to be able to use the try-with-resources statement.

css.php best counter