Исключение, выходящее из 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;
}