Исключение из метода close() в try-with-resource

Я читал о try-in-resource в JDK7, и пока я думал о том, чтобы обновить мое приложение для работы с JDK7, я столкнулся с этой проблемой.

При использовании BufferedReader, например, write throws IOException и close throws IOException.. в блоке catch я заинтересован в исключении 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?

В большинстве случаев я помещаю ресурс в try/catch внутри блока finally, не заботясь о его обработке.

Ответ 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 оператора броска.

Сообщение "Исключение из конструктора" будет напечатано, а исключение, созданное конструктором, будет подавлено, это означает, что вы не можете его поймать.

2. Конструктор throw in удален.

Теперь трассировка стека будет печатать "Исключение из метода" и "Подавлено: исключение из закрываемого" ниже. Здесь вы также не можете поймать исключенное исключение, созданное методом 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 a close exception and it can be ignored
    }

    return theData;
}

source: Закрыть ресурс тихо используя try-with-resources