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.)
Note that if you're using JDK 7+, then most uses of the finally block can be eliminated, simply by using a try-with-resources statement.
Style 1
If a method throws all exceptions, then it may use a finally with no catch :
import java.io.*; 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 is 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.*; 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; 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()) ; }
|
|