【问题标题】:Exception coming out of close() in try-with-resource [duplicate]try-with-resource 中的 close() 出现异常 [重复]
【发布时间】:2014-01-06 14:34:27
【问题描述】:

我正在阅读有关 JDK7 中的 try-with-resource 的信息,而当我考虑升级我的应用程序以使用 JDK7 运行时,我遇到了这个问题..

例如,当使用 BufferedReader 时,write 抛出 IOException,close 抛出 IOException.. 在 catch 块中,我担心 write 抛出的 IOException.. 但我不太关心 close 抛出的那个..

数据库连接也有同样的问题.. 和任何其他资源..

例如,我创建了一个可自动关闭的资源:

public class AutoCloseableExample implements AutoCloseable {

    public AutoCloseableExample() throws IOException{
        throw new IOException();
    }

    @Override
    public void close() throws IOException {
        throw new IOException("An Exception During Close");
    }

}

现在使用时:

public class AutoCloseTest {

    public static void main(String[] args) throws Exception {
        try (AutoCloseableExample example = new AutoCloseableExample()) {
            System.out.println(example);

            throw new IOException("An Exception During Read");
        } catch (Exception x) {
            System.out.println(x.getMessage());
        } 
    }

}

如何在不必为 BufferedReader 等类创建包装器的情况下区分此类异常?

大多数情况下,我将资源关闭在 finally 块内的 try/catch 中,而不关心如何处理它。

【问题讨论】:

  • 我说的是整体概念..反正..我现在加个代码sn-p..

标签: java java-7 try-with-resources


【解决方案1】:

让我们考虑一下这个类:

public class Resource implements AutoCloseable {

    public Resource() throws Exception {
        throw new Exception("Exception from constructor");
    }

    public void doSomething() throws Exception {
        throw new Exception("Exception from method");
    }

    @Override
    public void close() throws Exception {
        throw new Exception("Exception from closeable");
    }
}

和 try-with-resource 块:

    try(Resource r = new Resource()) {
        r.doSomething();
    } catch (Exception ex) {
        ex.printStackTrace();
    }

1. 3 个 throw 语句全部启用。

将打印消息“来自构造函数的异常”,并且构造函数抛出的异常将被抑制,这意味着您无法捕获它。

2. 构造函数中的 throw 被移除。

现在堆栈跟踪将在下面打印“来自方法的异常”和“已抑制:来自可关闭的异常”。这里你也无法捕捉到close方法抛出的抑制异常,但是你会收到关于抑制异常的通知。

3. 构造函数和方法的抛出被移除。

正如您可能已经猜到的那样,将打印“可关闭的异常”。

重要提示:在上述所有情况下,您实际上是在捕获所有异常,无论它们是在哪里引发的。因此,如果您使用 try-with-resource 块,则不需要用另一个 try-catch 包装该块,额外的块根本没有用。

希望对你有帮助:)

【讨论】:

  • 感谢您的贡献.. 我完全理解这一点.. 我正在考虑的问题是如何区分从 doSomething() 和 close() 方法等方法抛出的异常,因为两者都抛出相同类型的异常.. doSomething() 值得捕获,因为流程中发生了某些事情.. 而 close() 抛出的异常在大多数情况下并不是那么重要,让我感到困惑..
  • 好的,现在我明白你的意思了。如果您想将异常与代码区分开来,您可以通过ex.getStackTrace()[0].getMethodName() 获取异常的方法名称。如果没有,您可以打印堆栈跟踪并阅读它。
【解决方案2】:

我建议使用如下示例中的标志:

static String getData() throws IOException {
    boolean isTryCompleted = false;
    String theData = null;
    try (MyResource br = new MyResource();) {

        theData = br.getData();
        isTryCompleted = true;

    } catch(IOException e) {
        if (!isTryCompleted )
            throw e;
        // else it's a close exception and it can be ignored
    }

    return theData;
}

来源:Close resource quietly using try-with-resources

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-25
    • 2016-03-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多