Wednesday, February 16, 2011

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.)
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 exceptions, 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())
;
}


No comments:

Post a Comment

Chitika