Исключение, выходящее из close() в попытке с ресурсом

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

Например, при использовании BufferedReader запись выдает IOException, а закрытие выдает 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, не особо заботясь об его обработке.


person Mohammed R. El-Khoudary    schedule 18.12.2013    source источник
comment
Я говорю об общей концепции.. в любом случае.. Сейчас я добавлю фрагмент кода..   -  person Mohammed R. El-Khoudary    schedule 18.12.2013


Ответы (2)


Рассмотрим класс:

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. Конструктор броска удален.

Теперь трассировка стека будет печатать Exception from method и Suppressed: Exception from closeable ниже. Здесь вы также не можете поймать подавленное исключение, выброшенное методом close, но вы будете уведомлены о подавленном исключении.

3. Броски из конструктора и метода удалены.

Как вы, наверное, уже догадались, будет напечатано Exception from closeable.

Важный совет: во всех вышеперечисленных ситуациях вы фактически перехватываете все исключения, независимо от того, где они были созданы. Поэтому, если вы используете блок try-with-resource, вам не нужно оборачивать блок другим блоком try-catch, дополнительный блок просто бесполезен.

Надеюсь, поможет :)

person Flying Dumpling    schedule 18.12.2013
comment
Спасибо за ваш вклад. Я полностью это понимаю.. проблема, о которой я думаю, заключается в том, как различать исключения, выдаваемые такими методами, как doSomething() и метод close(), поскольку оба они вызывают одно и то же тип исключения.. doSomething () заслуживает улова, поскольку что-то происходит в потоке... в то время как исключение, выдаваемое из close(), в большинстве случаев не так уж важно и сбивает меня с толку.. - person Mohammed R. El-Khoudary; 18.12.2013
comment
Хорошо, теперь я понимаю, о чем ты. Если вы хотите отличить исключения от кода, вы можете получить имя метода исключения с помощью ex.getStackTrace()[0].getMethodName(). Если нет, вы можете просто распечатать трассировку стека и прочитать ее. - person Flying Dumpling; 19.12.2013

Я бы предложил использовать флаг, как в следующем примере:

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

источник: тихо закройте ресурс с помощью try-with-resources

person vtsamis    schedule 02.01.2018