关闭可能抛出异常的资源

3
  • 从池中获取Connection(这可能会抛出异常)
  • 使用连接创建Statement(也可能会抛出异常)
  • 使用该语句执行SQL查询并将其存储在ResultSet中(也可能会抛出异常)
  • 对查询结果进行处理
  • 关闭ResultSet(异常!)
  • 关闭Statement(异常!)
  • 关闭Connection(异常!)

看看这段代码:

    Connection  conn = null;
    Statement   st   = null;
    ResultSet   set  = null;
    try {
        conn    = Database.getConnection();
        st      = conn.createStatement();
        set     = st.executeQuery("SELECT * FROM THING");

        // <-- Do stuff
    } catch (Exception e) {

    } finally {
        // Close set if possible
        if (set != null) {
            try {
                set.close();
            } catch (Exception e) {

            }
        }

        // Close statement if possible
        if (st != null) {
            try {
                st.close();
            } catch (Exception e) {

            }
        }

        // Close connection if possible
        if (conn != null) {
            try {
                conn.close();
            } catch (Exception e) {

            }
        }
    }

finally块是我关闭资源的地方。正如您所看到的,它非常凌乱。我的问题是:这是清理这些资源的正确方法吗?


Guava的Closer可以在Java 6中模拟try-with-resource。http://wil.boayue.com/blog/2013/09/13/java-7-automatic-resource-management/ - 而无数的closeQuietly(Closable)方法可以帮助你缩短代码片段(尽管只是半正确的,因为关闭资源时出现异常可能意味着写操作失败,因此不应被忽略)。 - zapl
3个回答

5

在Java 1.7之前,你的代码是捕获可关闭资源异常的正确方式,只需将Exception替换为SQLException即可。

从Java 1.7开始,你可以使用"try-with-resources"语句,它允许你声明资源,在try块完成时自动调用close(),避免了繁琐的finally代码。

try (Connection conn = Database.getConnection(); Statement st = conn.createStatement();
     ResultSet set = st.executeQuery("SELECT * FROM THING")) {
   // Your "try" code as before
}
catch (SQLException e) {
   // Handle as before
}
// No "finally" to clean up resources needed!

他是否应该真正使用try-with-resources?因为在除了关闭之外的所有情况下都有效的情况下,try-with-resources将抛出on-close异常,而发布的代码则不会。 - Nathan Hughes
@NathanHughes 在这里忽略异常并不是什么大问题,因为它只是一个读取操作,而且在关闭时通常不会抛出异常。我猜这就是为什么 try-with-resource 没有内置的方法来忽略关闭错误,尽管它们确实对应用程序逻辑毫无意义,一旦它能够读取整个数据。 - zapl

1

0

是的,但你可以通过编写可重用的代码(最好在实用类中)使其看起来更漂亮

public static void close(Statement st) {
    if (st != null) {
        try {
            st.close();
        } catch (SQLException e) {
            // log exception
        }
    }
}

并在finally块中使用此方法。为ConnectionResultSet添加类似的方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接