Следующее решение правильно генерирует исключение, если закрытие завершается неудачно, не скрывая возможное исключение до закрытия.
try {
InputStream in = new FileInputStream(file);
try {
// work
in.close();
} finally {
Closeables.closeQuietly(in);
}
} catch(IOException exc) {
// kernel panic
}
Это работает, потому что повторный вызов close не имеет никакого эффекта .
Это зависит от guava Closeables , но при желании можно написать собственный метод closeQuietly, как показано squiddle (см. Также serg10 ).
Сообщение об ошибке закрытия, в общем случае, важно, потому что close может записать в поток некоторые окончательные байты, например, из-за буферизации. Следовательно, ваш пользователь хочет знать, если это не удалось, или вы, вероятно, хотите действовать как-то. Конечно, это не может быть правдой в конкретном случае FileInputStream, я не знаю (но по уже упомянутым причинам я думаю, что лучше сообщать об ошибке закрытия, если она все равно произойдет).
Приведенный выше код немного сложен для понимания из-за структуры встроенных блоков try. Это можно считать более понятным с помощью двух методов, один из которых генерирует IOException, а другой - его перехватывает. По крайней мере, я бы выбрал это.
private void work() throws IOException {
InputStream in = new FileInputStream(file);
try {
// work
in.close();
} finally {
Closeables.closeQuietly(in);
}
}
public void workAndDealWithException() {
try {
work();
} catch(IOException exc) {
// kernel panic
}
}
На основе http://illegalargumentexception.blogspot.com/2008/10/java-how-not-to-make-mess-of-stream.html (на что ссылается Макдауэлл).