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

Posted

技术标签:

【中文标题】谁在 close 方法中捕获异常?(try-with-resources)【英文标题】:Who catch exception, arise in close method?(try-with-resources) 【发布时间】:2014-07-13 09:39:36 【问题描述】:

接口AutoClosable具有以下方法声明:

void close()  throws Exception

因此我们看到方法 close 可以抛出异常。

当我编写代码尝试使用资源时,它看起来像这样:

private static void printFileJava7() throws IOException 

    try(FileInputStream input = new FileInputStream("file.txt")) 

        int data = input.read();
        while(data != -1)
            System.out.print((char) data);
            data = input.read();
        
    

在这段代码中没有异常处理。

我不明白如果 close 方法抛出异常会发生什么。

【问题讨论】:

【参考方案1】:

Java 在 try-with-resources 块中捕获并抑制 close 方法抛出的异常。

您可以在此处阅读有关此内容的更多信息,尤其是第二个代码示例之后的段落。 http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

【讨论】:

我认为这就是 OP 正在寻找的。 +1。我从您正在链接的文档中添加了一个引号,这样如果 OP 想要检索被抑制的异常知道该怎么做:You can retrieve these suppressed exceptions by calling the Throwable.getSuppressed method from the exception thrown by the try block.【参考方案2】:

AutoClosable 中定义的 close() 方法抛出异常是对的。然而,扩展 AutoClosable 的其他名为 Closable 的接口重新定义了此方法,如下所示:

void close() throws IOException

所有 IO 相关的类都实现了Closable,所以它们的close() 方法会抛出IOException。但是您的方法也会抛出它,因此在您的代码中没有人会捕获此异常。与往常一样,如果之前没有人捕获它,它将被应用程序的上层或 JVM 本身捕获。

【讨论】:

但是否会在我的方法中捕获 IOException?我会在 cloase 方法中捕获异常抛出吗?【参考方案3】:

来自jls about Compile-Time Checking of Exceptions

当涉及接口时,一个以上的方法声明可能会被一个覆盖声明覆盖。在这种情况下,覆盖声明必须具有与所有覆盖声明兼容的 throws 子句(第 9.4.1 节)。

所以当你有类似的东西时

static class AC implements AutoCloseable 
    @Override
    public void close() throws Exception 
        throw new Exception("btooom!");
    
    public void ac() 
        System.out.println("no");
    


public static void main(String[] args) throws Exception 
    try(AC ac = new AC()) 
        ac.ac();
    

然后你要么向周围的 try 块添加一个 catch 子句,要么添加一个 throws 声明。

对于FileInputStream 并应用jsl 声明的内容,AutoCloseable 的关闭方法是来自Closeable 的overriden,因此您只需捕获IOException 或添加它to throws 子句。

进一步了解 AutoCloseable#close 状态的 javadocs

虽然此接口方法被声明为抛出异常,但强烈建议实现者声明关闭方法的具体实现以抛出更具体的异常,或者如果关闭操作不会失败,则根本不抛出异常。

【讨论】:

【参考方案4】:

这个特定场景的关键是“被抑制的异常”。

"每当体内抛出异常,然后跟随 通过 try-with-resources 语句抛出的异常,只有 在 try 的主体中抛出的异常有资格被捕获 异常处理代码。所有其他异常都被视为被抑制的异常”

Java 7 中的新概念。因此,您将获得与仅 printfileJava7 类引发异常时相同的输出,因为 close() 方法引发的 CloseException 将被抑制。

请参考When two exceptions are thrown by the try-with-resources construct链接。您所问的具体情况是什么

【讨论】:

【参考方案5】:

您需要在方法 printFileJava7() 中有一个 catch 块,然后是 try。如果你不想在这里捕获它,你需要在调用方法 printFileJava7() 的方法中处理它。我们必须捕获其中一层,否则它将被传播回调用客户端。

【讨论】:

以上是关于谁在 close 方法中捕获异常?(try-with-resources)的主要内容,如果未能解决你的问题,请参考以下文章

如何在try-with-resource语句中捕获close方法引发的异常

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

生成器的throw和close方法

谁在调用删除?

数据访问对象 (DAO) 中的方法应该抛出还是捕获其异常? [关闭]

在 RunWorkerCompleted 中捕获未处理的异常 [关闭]