Исключение, выходящее из close() в try-with-resource

Я читал о try-with-resource В 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, не заботясь о его обработке.

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 оператора броска включены.

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

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

теперь трассировка стека будет печатать "исключение из метода" и "Подавлено: исключение из closeable" ниже. Здесь вы также не можете поймать подавленное исключение, вызванное методом close, но вы будете nofitied о подавленном исключении.

3. выбрасывает из конструктора и метода удаляются.

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

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

надеюсь, что это помогает :)


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

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