【问题标题】:Nested try blocks - does this have a use?嵌套的 try 块 - 这有用吗?
【发布时间】:2016-01-05 17:20:18
【问题描述】:

我遇到了一段类似这样的代码

try
{
    try (SomeResource res = new SomeResource())
    {
        // "\(o.o)/" *BOO*
    }
}
catch (SomeException e)
{
    e.letsNotIgnoreTheException();
}

我想不出使用两个 try 块的单一理由。我问过的其他人也想不出一个。

我想知道,这是否仅仅是 需要一些重构的方法,或者如果外部尝试确实有一些用处(特别是因为我发现了几次,但又一次, 有人可能只是误解了 try-with-resources)。

【问题讨论】:

    标签: java try-catch


    【解决方案1】:

    鉴于您的实际代码中没有额外的控制流或尝试构造,您的代码等效于:

        try (SomeResource res = new SomeResource()) {
            // "\(o.o)/" *BOO*
        } catch (SomeException e) {
            e.letsNotIgnoreThisException();
        }
    

    请注意:

    • try-with-resources 在异常处理之前执行res.close()
    • 因此e.letsNotIgnoreThisException() 被调用之后 res.close()
    • *BOO* 行引发的任何其他异常都必须得到适当处理(即捕获或声明)

    在try-with-resources中解释资源关闭和异常处理的执行顺序的关键行在这里描述:

    http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

    引用:

    注意: try-with-resources 语句可以像普通的 try 语句一样有 catch 和 finally 块。在 try-with-resources 语句中,任何 catch 或 finally 块都会在声明的资源关闭后运行。

    【讨论】:

      【解决方案2】:
      【解决方案3】:

      如果外部的try-catch除了内部的try之外什么都没有,那么就没有必要了,因为你可以将它们合二为一。但是,如果外面的 try-catch 里面有别的东西,语义可能会有所不同。

      【讨论】:

        【解决方案4】:

        在访问数据库时,这种模式经常发生 - 主要是为了确保正确关闭资源,同时也是为了在不停止查询的情况下处理每条记录时处理错误。

            try {
                ResultSet rs = query.executeQuery();
                try {
                    // Each row.
                    while (rs.next()) {
                        // Handle each record.
                        try {
                            // One row.
                        } catch (SomeException se) {
                            // Deal with exception when processing the row so we do not abort the whole query.
                        }
                    }
                } catch (SQLException se) {
                    // Perhaps database connection went down during the iteration.
                } finally {
                    // Remember to close - whatever happens.
                    rs.close();
                }
            } catch (Exception ex) {
                // Probably the query is malformed or something.
                log.error("failed", ex);
            }
        

        【讨论】:

          【解决方案5】:

          已证伪:

          这与单个 try 块的执行方式不同 - try-with-resources 转换为在 finally 块中关闭资源,该块执行 after catch 块,而 try-with-resources 在嵌套的 try 块执行 before 外部 catch 块。

          如果您想在执行 catch 块之前关闭 SomeResource 资源,这可能会很有用。

          例如,如果您正在将某些内容写入文件并且在出错时想要删除该文件内容并将错误消息写入同一文件(我知道虚拟示例),您可以通过先关闭资源来执行此操作,然后删除文件并将错误写入新的流/资源中。

          【讨论】:

          • Jiri,这是我的第一个假设,但我测试了它,这是不正确的 - try-with-resources 与 finally 块相同,资源被关闭 before catch 和 finally。请参阅文本“在声明的资源关闭后运行任何 catch 或 finally 块”。在 oracle 文档中...
          • @vikingsteve 我的立场是正确的,感谢您指出这一点。
          • 不用担心。这实际上改变了我的理解,因为 try-with-resources 与 finally 块“技术上” 不同,尽管在大多数情况下它应该无关紧要。我今天也学到了一些新东西:)
          猜你喜欢
          • 1970-01-01
          • 2013-08-11
          • 1970-01-01
          • 1970-01-01
          • 2023-03-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-11-07
          相关资源
          最近更新 更多