异常来自 close() 在 try-with-resource 中

2022-09-02 22:12:40

我正在阅读有关JDK7中的资源试用的信息,当我考虑升级我的应用程序以使用JDK7运行时,我遇到了这个问题。

例如,当使用 BufferedReader 时,写入会引发 IOException,而 close 会引发 IOException。在捕获块中,我担心由写入抛出的IOException。但我不会太在乎关闭时扔掉的那个。

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

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

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 等类创建包装器?

大多数情况下,我将资源关闭在最终块内的尝试/捕获中,而不太关心处理它。


答案 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(Resource r = new Resource()) {
        r.doSomething();
    } catch (Exception ex) {
        ex.printStackTrace();
    }

1. 启用所有 3 个 throw 语句。

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

2. 删除插入构造函数。

现在,堆栈跟踪将在下面打印“来自方法的异常”和“已抑制:来自可关闭的异常”。在这里,您也无法捕获由 close 方法引发的已抑制异常,但您将对抑制的异常进行筛选。

3. 删除构造函数和方法中的抛出。

您可能已经猜到了“可关闭的例外”将被打印出来。

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

希望它能帮助:)


答案 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;
}

来源:使用资源试用悄悄关闭资源


推荐