Finally and catch

The finally block is used to ensure resources are recovered regardless of any problems that may occur.

There are several variations for using the finally block, according to how exceptions are handled. (See the excellent book The Java Programming Language by Arnold, Gosling, and Holmes for related information.)

If you're using JDK 7+, then most uses of the finally block can be eliminated, simply by using a try-with-resources statement. If a resource doesn't implement AutoCloseable, then a finally block will still be needed, even in JDK 7+. Two examples would be:

JDK < 7, and resources that aren't AutoCloseable
The following examples are appropriate for older versions of the JDK. They are also appropriate in JDK 7+, but only for resources that don't implement AutoCloseable.

Style 1

If a method throws all exceptions, then it may use a finally with no catch:


import java.io.*;

/** Before JDK 7. */
public final class SimpleFinally {
  
  public static void main(String... aArgs) throws IOException {
    simpleFinally("C:\\Temp\\test.txt");
  }
  
  private static void simpleFinally(String aFileName) throws IOException {
    //If this line throws an exception, then neither the try block
    //nor the finally block will execute.
    //That's a good thing, since reader would be null.
    BufferedReader reader = new BufferedReader(new FileReader(aFileName));
    try {
      //Any exception in the try block will cause the finally block to execute
      String line = null;
      while ((line = reader.readLine()) != null) {
        //process the line...
      }
    }
    finally {
      //The reader object will never be null here.
      //This finally is only entered after the try block is 
      //entered. But, it's NOT POSSIBLE to enter the try block 
      //with a null reader object.
      reader.close();
    }
  }
}
 

Style 2

If a method handles all of the checked exceptions that may be thrown by its implementation, then an interesting variation is to nest a try..finally within a try..catch. This style is particularly useful when the finally block throws the same exceptions as the rest of the code (which is common with java.io operations.) Although this style may seem slightly complex, it appears to be superior to alternative styles:


import java.io.*;
import java.util.logging.*;

/** Before JDK 7. */
public final class NestedFinally {
  
  public static void main(String... aArgs) {
    nestedFinally("C:\\Temp\\test.txt");
  }
  
  private static void nestedFinally(String aFileName) {
    try {
      //If the constructor throws an exception, the finally block will NOT execute
      BufferedReader reader = new BufferedReader(new FileReader(aFileName));
      try {
        String line = null;
        while ((line = reader.readLine()) != null) {
          //process the line...
        }
      }
      finally {
        //no need to check for null
        //any exceptions thrown here will be caught by 
        //the outer catch block
        reader.close();
      }
    }
    catch(IOException ex){
      fLogger.severe("Problem occured : " + ex.getMessage());
    }
  }
  
  private static final Logger fLogger =
    Logger.getLogger(NestedFinally.class.getPackage().getName())
  ;
}
 

Style 3

A more verbose style places a catch within the finally. This style is likely the least desirable, since it has the most blocks:


import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.logging.Logger;

/** Before JDK 7. */
public final class CatchInsideFinally {
  
  public static void main(String... aArgs) {
    catchInsideFinally("C:\\Temp\\test.txt");
  }
  
  private static void catchInsideFinally(String aFileName) {
    //Declared here to be visible from finally block
    BufferedReader reader = null;
    try {
      //if this line fails, finally will be executed, and reader will be null
      reader = new BufferedReader(new FileReader(aFileName));
      String line = null;
      while ( (line = reader.readLine()) != null ) {
        //process the line...
      }
    }
    catch(IOException ex){
      fLogger.severe("Problem occured : " + ex.getMessage());
    }
    finally {
      try {
        //need to check for null
        if ( reader != null ) {
          reader.close();
        }
      }
      catch(IOException ex){
        fLogger.severe("Problem occured. Cannot close reader : " + ex.getMessage());
      }
    }
  }
  
  private static final Logger fLogger =
    Logger.getLogger(CatchInsideFinally.class.getPackage().getName())
  ;
} 



See Also :
Always close streams
Recovering resources
Use finally to unlock
Would you use this technique?
Yes   No   Undecided   
© 2014 Hirondelle Systems | Source Code | Contact | License | RSS
Individual code snippets can be used under this BSD license - Last updated on September 21, 2013.
Over 2,000,000 unique IPs last year - Built with WEB4J.
- In Memoriam : Bill Dirani -