Есть ли элегантный способ обработки исключений, возникающих в finally
блоке?
Например:
try {
// Use the resource.
}
catch( Exception ex ) {
// Problem with the resource.
}
finally {
try{
resource.close();
}
catch( Exception ex ) {
// Could not close the resource?
}
}
Как избежать try
/ catch
в finally
блоке?
Resource
=>Closeable
?Обычно я использую один из следующих
closeQuietly
методовorg.apache.commons.io.IOUtils
:источник
Если вы используете Java 7 и
resource
реализует егоAutoClosable
, вы можете сделать это (используя InputStream в качестве примера):источник
Возможно, немного чрезмерно, но может быть полезно, если вы позволяете исключениям всплывать и вы не можете ничего регистрировать из своего метода (например, потому что это библиотека, и вы бы предпочли, чтобы вызывающий код обрабатывал исключения и ведение журнала):
ОБНОВЛЕНИЕ: я изучил это немного больше и нашел отличное сообщение в блоге от того, кто явно думал об этом больше, чем я: http://illegalargumentexception.blogspot.com/2008/10/java-how-not-to-make -mess-of-stream.html Он идет еще дальше и объединяет два исключения в одно, что, на мой взгляд , может быть полезно в некоторых случаях.
источник
ignore
исключениеНачиная с Java 7 вам больше не нужно явно закрывать ресурсы в блоке finally, вместо этого вы можете использовать синтаксис try -with-resources. Оператор try-with-resources - это оператор try, объявляющий один или несколько ресурсов. Ресурс - это объект, который необходимо закрыть после того, как программа завершит работу с ним. Оператор try-with-resources гарантирует, что каждый ресурс будет закрыт в конце оператора. Любой объект, реализующий java.lang.AutoCloseable, который включает все объекты, реализующие java.io.Closeable, может использоваться как ресурс.
Предположим следующий код:
Если произойдет какое-либо исключение, метод close будет вызываться для каждого из этих трех ресурсов в порядке, обратном тому, в котором они были созданы. Это означает, что метод close будет вызываться сначала для ResultSetm, затем для оператора и в конце для объекта Connection.
Также важно знать, что любые исключения, возникающие при автоматическом вызове методов close, подавляются. Эти подавленные исключения можно получить с помощью метода getsuppressed (), определенного в классе Throwable .
Источник: https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
источник
Игнорирование исключений, которые происходят в блоке 'finally', как правило, является плохой идеей, если неизвестно, какими будут эти исключения и какие условия они будут представлять. В обычном
try/finally
шаблоне использованияtry
блок переводит вещи в состояние, которого внешний код не ожидает, иfinally
блок восстанавливает состояние этих вещей до того, что ожидает внешний код. Внешний код, который перехватывает исключение, обычно ожидает, что, несмотря на исключение, все было восстановлено доnormal
штат. Например, предположим, что какой-то код запускает транзакцию, а затем пытается добавить две записи; блок «finally» выполняет операцию «откат, если не зафиксирован». Вызывающий может быть подготовлен к возникновению исключения во время выполнения второй операции «добавления» и может ожидать, что, если он уловит такое исключение, база данных будет в состоянии, в котором она была до попытки выполнения любой из этих операций. Если, однако, во время отката возникает второе исключение, могут произойти неприятности, если вызывающий объект сделает какие-либо предположения о состоянии базы данных. Ошибка отката представляет собой серьезную кризис, который не должен быть обнаружен кодом, ожидающим простого исключения «Не удалось добавить запись».Лично я предпочитаю использовать метод finally, который будет перехватывать возникающие исключения и заключать их в «CleanupFailedException», признавая, что такой сбой представляет собой серьезную проблему, и такое исключение не следует воспринимать легкомысленно.
источник
Одно решение, если два исключения - это два разных класса
Но иногда не избежать второй попытки. например, для закрытия потока
источник
Почему вы хотите избежать дополнительной блокировки? Поскольку блок finally содержит «нормальные» операции, которые могут вызывать исключение, и вы хотите, чтобы блок finally выполнялся полностью, вы ДОЛЖНЫ перехватывать исключения.
Если вы не ожидаете, что блок finally вызовет исключение, и вы не знаете, как обработать исключение в любом случае (вы бы просто сбросили трассировку стека), позвольте исключению пузыриться вверх по стеку вызовов (удалите try-catch из finally блок).
Если вы хотите уменьшить количество наборов текста, вы можете реализовать «глобальный» внешний блок try-catch, который будет перехватывать все исключения, созданные в блоках finally:
источник
После долгих размышлений я считаю, что лучше всего подходит следующий код:
Этот код гарантирует следующее:
источник
Если вы можете, вы должны сначала протестировать, чтобы избежать состояния ошибки.
Кроме того, вы, вероятно, должны перехватывать только исключения, из которых вы можете восстановить, если вы не можете восстановить, пусть они распространяются на верхний уровень вашей программы. Если вы не можете проверить состояние ошибки, вам придется окружить свой код блоком try catch, как вы это уже сделали (хотя я бы по-прежнему рекомендовал отлавливать определенные ожидаемые ошибки).
источник
Вы можете преобразовать это в другой метод ...
источник
Я обычно так делаю:
Обоснование: если я закончил с ресурсом и единственная проблема, с которой я столкнулся, - это его закрытие, я мало что могу с этим поделать. Нет смысла убивать весь поток, если я все равно закончил с ресурсом.
Это один из случаев, когда, по крайней мере, для меня безопасно игнорировать это проверенное исключение.
По сей день у меня не было проблем с использованием этой идиомы.
источник
Работа выполнена. Нет нулевых тестов. Единый улов, включая исключения для получения и выпуска. Конечно, вы можете использовать идиому Execute Around, и вам нужно написать ее только один раз для каждого типа ресурса.
источник
Переход
Resource
от лучшего ответа кCloseable
Реализует потоки
Closeable
Таким образом, вы можете повторно использовать метод для всех потоковисточник
Я столкнулся с аналогичной ситуацией, когда я не мог использовать try с ресурсами, но я также хотел обработать исключение, исходящее из закрытия, а не просто регистрировать и игнорировать его, как это делает механизм closeQuietly. в моем случае я на самом деле не имею дело с потоком вывода, поэтому сбой при закрытии представляет больший интерес, чем простой поток.
источник