Try-with-resources:我必须抛出或捕获 close() 方法的异常吗? [复制]

Posted

技术标签:

【中文标题】Try-with-resources:我必须抛出或捕获 close() 方法的异常吗? [复制]【英文标题】:Try-with-resources: Must I throw or catch the close() method's exceptions? [duplicate] 【发布时间】: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)。 【参考方案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 子句中放置多个异常,或者您可以简单地捕获所需的最外层异常。

【讨论】:

以上是关于Try-with-resources:我必须抛出或捕获 close() 方法的异常吗? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

try-with-resources 或 close() 困境

1.9 try-with-resources 优先于try-finally

谁在 close 方法中捕获异常?(try-with-resources)

try-with-resources 中的两种关闭方法

如何修复“SQLServerException:连接已关闭”。在这个 Try-With-Resources 块中出现?

20172326 《程序设计与数据结构》第九周学习总结