Saturday, December 19, 2009

5.3 Finally for Closure











 < Day Day Up > 







5.3 Finally for Closure





In the try-catch-finally

triad, is the finally clause is often

neglected. This clause allows you to write code that will run

regardless of the outcome of the method. Whether the code within a

try block throws an exception or not, code in a

finally block will be executed by the compiler.

The JDBC program in Example 5-6 shows how

finally is used.







Example 5-6. Closing database resources with finally


package oreilly.hcj.finalstory;

public class FinallyForClosure {



public int getValue(final Connection conn, final String sql)

throws SQLException {

int result = 0;

Statement stmt = null;

ResultSet rs = null;

try {

stmt = conn.createStatement( );

rs = stmt.executeQuery(sql);

if (rs.next( )) {

result = rs.getInt(1);

}

} catch (final SQLException ex) {

throw ex;

} finally {

if (rs != null) {

rs.close( );

}

if (stmt != null) {

stmt.close( );

}

}

return result;

}



}






In this code, even if a SQLException is thrown,

the method will attempt to close the ResultSet and

Statement and thus release the resources they were

consuming. In this manner, you can ensure that the database resources

are closed no matter what happens. It is good practice to use

finally blocks whenever you seize external

resources inside of a try block.





Although there is nothing technically wrong with the code in Example 5-6, you can make it even better. To understand

how, consider the catch clause:





    } catch (final SQLException ex) {

throw ex;

} finally {




The catch clause is this example is superfluous.

To use a finally block, you do not have to catch

any thrown exceptions; you can merely ignore them and let them be

thrown by the method. When you reconsider the getValue(

)
method, it becomes obvious that not catching the

exceptions is a good idea.





The getValue( ) method may throw a

SQLException during the course of the method.

Whatever happens, you need to close the database resources used in

the call to prevent a resource leak. However, the attempted closure

of these resources could generate SQLException

instances as well. For this reason, you must declare that the method

throws SQLException. The classic solution to this

problem is to catch the exception from the try

block and rethrow it, as shown in Example 5-6.

However, a better approach is to use the finally

block without catching the exceptions at all:





package oreilly.hcj.finalstory;

public class FinallyForClosure {



public int getValue2(final Connection conn, final String sql)

throws SQLException {

int result = 0;

Statement stmt = null;

ResultSet rs = null;

try {

stmt = conn.createStatement( );

rs = stmt.executeQuery(sql);

if (rs.next( )) {

result = rs.getInt(1);

}

} finally {

if (rs != null) {

rs.close( );

}

if (stmt != null) {

stmt.close( );

}

}

return result;

}



}




Because this try block contains a

finally block but no catch

block, any exceptions thrown in the code will be merrily shot out of

the method call, and the finally block will still

be executed. This results in a much cleaner piece of code.

















     < Day Day Up > 



    No comments: