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.
|
No comments:
Post a Comment