Jon
Jon

Reputation: 359

What are the benefits to using a try-finally block for working with an input stream?

Here is a Java example I found online:

try{
      //use buffering
      InputStream file = new FileInputStream("quarks.ser");
      InputStream buffer = new BufferedInputStream(file);
      ObjectInput input = new ObjectInputStream (buffer);
      try{
        //deserialize the List
        List<String> recoveredQuarks = (List<String>)input.readObject();
        //display its data
        for(String quark: recoveredQuarks){
          System.out.println("Recovered Quark: " + quark);
        }
      }
      finally{
        input.close();
      }
} catch(ClassNotFoundException ex){
      //some exception handling
}

In the above, what are the benefits of using a try-finally block to execute some processing with the input before closing the input? In other words, what benefits would the code above have over something like this:

try{
      //use buffering
      InputStream file = new FileInputStream("quarks.ser");
      InputStream buffer = new BufferedInputStream(file);
      ObjectInput input = new ObjectInputStream (buffer);
      List<String> recoveredQuarks = (List<String>)input.readObject();
      for(String quark: recoveredQuarks){
          System.out.println("Recovered Quark: " + quark);
      }
      input.close();
} catch(ClassNotFoundException ex){
      //some exception handling
}

Upvotes: 0

Views: 1042

Answers (2)

Stephen C
Stephen C

Reputation: 719336

The benefit of using try / finally ... or better still try-with-resource, is that it largely prevents resource leaks such as these:

and so on. Generally speaking, these problems happen because there is some path through the code where the stream / socket / whatever doesn't get closed. If that path is taken too often, attempts to open new streams, etcetera fail because the application has used all of the file descriptors available to it. If you use finally correctly you can ensure that descriptors are released in all circumstances that matter.

It should also be noted that example you found on the net is not correct ... at least in theory. If the constructors for BufferedInputStream or ObjectInputStream were to throw an exception, then the finally block would not be executed, and the FileInputStream would be leaked.

A better way to write it is as follows:

try (InputStream file = new FileInputStream("quarks.ser");
     InputStream buffer = new BufferedInputStream(file);
     ObjectInputStream input = new ObjectInputStream (buffer)) {

     // do stuff

} catch (ClassNotFoundException ex){
      // handling exception
}

Upvotes: 3

Alex
Alex

Reputation: 1205

There is a big difference: Imagine the following situation

  InputStream file = new FileInputStream("quarks.ser");
  InputStream buffer = new BufferedInputStream(file);
  ObjectInput input = new ObjectInputStream (buffer);
  try{
    //do sth
    throw new RuntimeException();
    //do sth else
  }
  finally{
    input.close();
  }

In that case, with a finally block, the exception is thrown, but the finally block is executed and your input therefore closed.

If your code instead was

  InputStream file = new FileInputStream("quarks.ser");
  InputStream buffer = new BufferedInputStream(file);
  ObjectInput input = new ObjectInputStream (buffer);
  //do sth
  throw new RuntimeException();
  //do sth else
  input.close();

Your InputStream would not get closed properly.


But since Java 7, the most elegant version would be to use try-with-resources, as mentioned in a comment to your question:

try (InputStream file = new FileInputStream ("quarks.ser");
    InputStream buffer = new BufferedInputStream (file);
    ObjectInput input = new ObjectInputStream (buffer);) {
  //do sth
  throw new RuntimeException ();
  //do sth else
}

Upvotes: 7

Related Questions