如何正确关闭资源 [英] How to Correctly Close Resources
问题描述
在清理一些代码时,FindBugs向我介绍了一些使用Connection,CallableStatement和ResultSet对象的JDBC代码.这是该代码的一个片段:
As I was cleaning up some code, FindBugs pointed me to a bit of JDBC code that uses Connection, CallableStatement, and ResultSet objects. Here's a snippet from that code:
CallableStatement cStmt = getConnection().prepareCall("...");
...
ResultSet rs = cStmt.executeQuery();
while ( rs.next() )
{
...
}
cStmt.close();
rs.close();
con.close();
FindBugs指出,这些应该在finally块内.我开始重构代码来做到这一点,然后开始想知道如何在finally块中处理代码.
FindBugs pointed out that these should be within a finally block. I started refactoring my code to do this and I started to wonder how to handle the code within the finally block.
创建Connection对象的CallableStatement可能会引发异常,而我的ResultSet对象保留为null.当我尝试关闭ResultSet时,我会收到NullPointerException,而我的Connection永远也不会关闭.实际上,此线程提出了相同的概念,并表明包装了close()调用空检查是个好主意.
It's possible that the creation of the CallableStatement of Connection objects would throw an exception, leaving my ResultSet object as null. When I try to close the ResultSet, I'd get a NullPointerException and my Connection would, in turn, never get closed. Indeed, this thread brings up the same concept and shows that wrapping your close() invocations in a null check is a good idea.
但是其他可能的例外呢?根据Java API规范,Statement.close()可能在如果发生数据库错误"时抛出SQLException.因此,即使我的CallableStatement不为null并且可以成功调用close(),我仍然可能会遇到异常,并且没有机会关闭其他资源.
But what about other possible exceptions? According to the Java API spec, Statement.close() can throw a SQLException "if a database error occurs". So, even if my CallableStatement is not null and I can successfully call close() on it, I might still get an exception and not have a chance to close my other resources.
我能想到的唯一故障安全"解决方案是将每个close()调用包装在其自己的try/catch块中,如下所示:
The only "fail safe" solution I can think of is to wrap each close() invocation in its own try/catch block, like this:
finally {
try {
cStmt.close();
} catch (Exception e) { /* Intentionally Swallow Exception */ }
try {
rs.close();
} catch (Exception e) { /* Intentionally Swallow Exception */ }
try {
con.close();
} catch (Exception e) { /* Intentionally Swallow Exception */ }
}
男孩,如果看起来还不错.有没有更好的方法可以解决这个问题?
Boy, if that doesn't look awful. Is there a better way to go about this?
推荐答案
我认为最好的答案已经被提及,但是我想提到您可以考虑可自动关闭资源的JDK 7新功能可能会很有趣.
I think the best answer has already being mentioned, but I thought it could be interesing to mention that you could consider the new JDK 7 feature of autoclosable resources.
try{
try(Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/hrdb", "obiwan", "kenobi");
Statement stm = conn.createStatement();
ResultSet rs = stm.executeQuery("select name from department")) {
while(rs.next()){
System.out.println(rs.getString("name"));
}
}
}catch(SQLException e){
//you might wanna check e.getSuppressed() as well
//log, wrap, rethrow as desired.
}
并不是所有人都可以立即迁移到JDK 7,但是对于那些可以开始使用开发人员预览版的人来说,这提供了一种有趣的做事方式,并且肯定会在不久的将来弃用其他方法.
Not all of us can migrate to JDK 7 now, but for those who can start playing with the developer preview, this offer an interesting way of doing things and certainly may deprecate other approaches in the near future.
这篇关于如何正确关闭资源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!