【问题标题】:Try-with-resources: Must I throw or catch the close() method's exceptions? [duplicate]Try-with-resources:我必须抛出或捕获 close() 方法的异常吗? [复制]
【发布时间】:2013-04-09 06:53:46
【问题描述】:

如果有错误,请纠正我:在 Java 7 的 try-with-resources 语句中,资源的 close() 方法抛出的任何异常都必须声明为由我的方法抛出,或者我必须将整个尝试包装在另一个 @ 987654322@ 捕获close() 抛出的任何异常。

如果是这样,我想知道我是否会充分利用它。我当然不想throw close() 抛出的异常,调用者不知道该怎么办。一个 try 包裹另一个 try 只是为了处理 close() 看起来不是很优雅,至少对我来说。

编辑:我想我不小心问了两个问题,其中一个是重复的。

问题 1. 我是否必须声明我的方法从 close() 方法抛出异常或将 try-with-resources 包装在另一个尝试中? (建议的副本中没有回答。)

问题2.有没有办法静默关闭资源? (显然是重复的,所以我把这句话排除在问题之外。希望这能让这个问题令人满意地独一无二。)

【问题讨论】:

  • 你有很多资源从close()扔过来的吗?
  • 只有几个,但我经常使用它们(ResultSet、BufferedReader、RandomAccessFile)。

标签: java exception-handling


【解决方案1】:

引用Java Language Specification ($14.20.3.2):

14.20.3.2 扩展的 try-with-resources

带有至少一个 catch 子句和/或 finally 子句的 try-with-resources 语句 子句称为扩展的 try-with-resources 语句。 扩展的 try-with-resources 语句的含义:

    试试 ResourceSpecification

捕获选择
终于选择

由以下对基本 try-with-resources 语句的翻译给出 (§14.20.3.1) 嵌套在 try-catchtry-finallytry-catch-finally 中 声明:

    试试 {
试试 ResourceSpecification

}
捕获选择
终于选择

翻译的效果是把ResourceSpecification“放在”try里面 陈述。这允许扩展的 try-with-resources 语句的 catch 子句 捕获由于任何资源的自动初始化或关闭而导致的异常。

所以,基本上,包装器已经实现了

【讨论】:

    【解决方案2】:

    来自the Java tutorial

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

    (强调我的)

    所以你可以简单地做

    try (BufferedReader br =
                   new BufferedReader(new FileReader(path))) {
        return br.readLine();
    }
    catch (IOException e) {
        // handle the exception that has been thrown by readLine() OR by close().
    }
    

    【讨论】:

    • 如果不调用catch并且没有finally块,资源会被关闭吗?
    • 点击链接阅读。
    • 这种方法并不能解决问题。对我来说,“正常”行为是:1)从 readLine 重新抛出异常 2)忽略 close 抛出的异常。按照您建议的方式进行操作,没有一种简单的方法可以知道异常是来自 readLine 还是来自 close。
    【解决方案3】:

    您不需要将 try-with-resources 包装在另一个 try-catch 块中,只需添加一个 catch 块:

    class Foo implements AutoCloseable {
        public void close() throws Exception {
            throw new Exception();
        }
    }
    
    public class Try {
        public static void main(final String[] args) {
            try(Foo f = new Foo()) {
                System.out.println("No op!");
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    【讨论】:

      【解决方案4】:

      您应该能够简单地添加适当的catch (Exception e) { } 子句。如果您需要对特定的进行特殊处理,或者您可以简单地捕获Exception,如果您需要它更广泛。

      try (Statement stmt = con.createStatement()) {
          ResultSet rs = stmt.executeQuery(query);
      
          while (rs.next()) {
              String coffeeName = rs.getString("COF_NAME");
              int supplierID = rs.getInt("SUP_ID");
              float price = rs.getFloat("PRICE");
      
              System.out.println(coffeeName + ", " + supplierID + ", " + 
                                 price + ", " + sales + ", " + total);
          }
      } catch (Exception e) {
          System.out.println("Exception while trying to through the queries. ", e);
      }
      

      由于是 Java 7,实际上您可以在每个 catch 子句中放置多个异常,或者您可以简单地捕获所需的最外层异常。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-07-27
        • 2016-04-13
        • 2017-03-15
        • 2014-01-06
        • 1970-01-01
        • 1970-01-01
        • 2016-04-04
        相关资源
        最近更新 更多