【问题标题】:Try-with-resources equivalent in Java 1.6Java 1.6 中的 Try-with-resources 等效项
【发布时间】:2014-06-29 23:41:42
【问题描述】:

我有以下代码:

    public class Main {

        public static void main(String[] args) throws SQLException {

            try (
                    Connection conn = DBUtil.getConnection(DBType.HSQLDB);
                    Statement stmt = conn.createStatement(
                            ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
                    ResultSet rs = stmt.executeQuery("SELECT * FROM tours");
                    ) {

            DBUtil.getConnection();

            } catch (SQLException e) {
                DBUtil.processException(e);
            } 

        }

    }

我使用此代码从数据库中获取数据。我的问题是我不允许使用 Java 1.7 编译器,必须使用 1.6。 如何翻译 try-with-resources-code 以与 1.6 编译器一起使用? 在这个特殊的 try 块中究竟发生了什么?

【问题讨论】:

  • 将括号之间的所有行放在try代码的开头,并将所有结束代码放在finally后面的所有catchs中。
  • (i) 将语句放在 try 代码中 (ii) 在 finally 块中关闭需要关闭的内容。
  • 就这么简单吗?好的,我认为 try-with-ressources 更复杂,因为我看到了一些奇怪的帖子
  • 为什么不能使用 Java 7 编译器?您可以将目标兼容性设置为 Java 6...
  • 这是一个大学项目,我们应该使用 1.6 编译器

标签: java try-catch try-with-resources


【解决方案1】:

Oracle 解释了 try-with-resources 的工作原理here

它的 TL;DR 是:
在 Java 1.6 中没有简单的方法可以做到这一点。问题是 Exception 中没有 Suppressed 字段。您可以忽略它并硬编码尝试和关闭都抛出不同异常时发生的情况,或者创建您自己的具有抑制字段的异常子层次结构。

在第二种情况下,上面的链接给出了正确的方法:

   AutoClose autoClose = new AutoClose();
   MyException myException = null;
   try {
       autoClose.work();
   } catch (MyException e) {
       myException = e;
       throw e;
   } finally {
       if (myException != null) {
           try {
               autoClose.close();
           } catch (Throwable t) {
               myException.addSuppressed(t);
           }
       } else {
           autoClose.close();
       }
   }  

等价于

try (AutoClose autoClose = new AutoClose()) {
    autoClose.work();
}

如果您想让它变得更简单而不是创建大量新的异常类,您将必须决定在 finally(t 或 e)内的 catch 子句中抛出什么。

PS。在上面的链接中也讨论了在 try 中处理多个变量声明。您需要正确完成它的代码量是惊人的。大多数人在 Java 1.6 中通过不处理 finally 块中的异常并使用 nullchecks 来走捷径。

【讨论】:

    【解决方案2】:

    这样做:

    Connection conn = null;
    Statement stmt = null;
    ResultSet rs = null;
    
    try {
        conn = DBUtil.getConnection(DBType.HSQLDB);
        stmt = conn.createStatement(
        ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        rs = stmt.executeQuery("SELECT * FROM tours");
    } catch (SQLException e) {
        DBUtil.processException(e);
    } finally {
        if(conn != null) {
            conn.close();
        }
        if(stmt != null) {
            stmt.close();
        }
        if(rs != null) {
            rs.close();
        }
    }
    

    【讨论】:

    • -1 这不等同于 try-with-resources。特别是在异常处理方面。
    • 多年的火焰战争,我们又回到了起点。在“Java 6 close resources”上进行简单的谷歌搜索将给出大量解释为什么这是不正确的,包括 SO 问题。 stackoverflow.com/questions/5782647/… 例如,从 3 年前开始(接受“使用 JDK 7,它就这么简单”的答案)
    • 不会关闭 finally 块中的语句需要另一个 try/catch 吗?
    【解决方案3】:

    我建议使用 apache 的 commons-dbutils 库,该库具有 DBUtils 类和 closecloseQuietly 方法。 代码如下所示:

    import org.apache.commons.dbutils.DBUtils;
    ...
    Connection conn = null;
    Statement stmt = null;
    ResultSet rs = null;
    
    try {
        conn = myOwnUtil.getConnection();
        stmt = conn.createStatement();
        rs = stmt.executeQuery( "SELECT * FROM table" ); // or any other custom query
    } catch ( SQLException e ) {
        <<handle exception here>>;
    } finally {
        DBUtils.closeQuietly( conn );
        DBUtils.closeQuietly( stmt );
        DBUtils.closeQuietly( rs );
        // or simply use DBUtils.close( conn, stmt, rs );
    }
    

    请注意,closeQuietly 不会抛出异常,而 close 可能会抛出 SQLException,因此请根据您自己的用例调整代码。

    如果你想关闭流,你可以使用 apache 的 commons-io 和 IOUtils 类,它也有 close 和 closeQuietly。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-30
      • 1970-01-01
      相关资源
      最近更新 更多