48

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

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

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

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

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

4

4 回答 4

40

引用Java 语言规范 ($14.20.3.2)

14.20.3.2 扩展的资源尝试

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

    尝试ResourceSpecification
        块
    捕获选择
    最后选择

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

    尝试{
        尝试资源
规范             块
    }
    捕获选择
    最终选择

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

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

于 2013-04-09T07:12:36.083 回答
25

来自Java 教程

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().
}
于 2013-04-09T07:07:34.393 回答
7

您不需要将 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();
        }
    }
}
于 2013-04-09T07:07:48.277 回答
2

您应该能够简单地添加适当的catch (Exception e) { }子句。如果您需要对特定的进行特殊处理,或者您可以简单地 catch 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 子句中放置多个异常,或者您可以简单地捕获所需的最外层异常。

于 2013-04-09T07:08:08.193 回答