如何正确关闭资源 [英] How to Correctly Close Resources

查看:155
本文介绍了如何正确关闭资源的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在清理一些代码时,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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆