Эффективный обзор Java (Серия из 79 частей)
Сегодня у нас есть тема, полностью соответствующая тому, о чем мы говорили на прошлой неделе. На прошлой неделе тема была посвящена финализаторам и очистителям. Одним из распространенных способов их использования является очистка ресурсов. В этом посте в блоге мы немного подробнее расскажем о лучшем способе, на который мы намекали в конце предыдущего поста.
Существует множество ресурсов, которые по той или иной причине необходимо вручную закрыть после использования. Это часто достигается с помощью метода close
для объекта. Мы, конечно, не хотим утекать ресурсы или оставлять предметы в наполовину обработанном состоянии. В этом случае мы можем рассмотреть возможность размещения метода close в блоке finally
. Например:
static List
Это будет работать просто отлично, это даже не выглядит так уж плохо. Это становится все более запутанным и подверженным ошибкам по мере того, как мы добавляем больше ресурсов.
static List
Это начинает становиться все более грубым и трудным для понимания. Я вообще правильно это сделал? Я не убежден. Это может быть легко испортить. Автор даже признает, что он годами путал этот шаблон в одной из своих книг, и никто этого не понимал. Даже при правильном коде есть тонкости с обработкой ошибок, которые обрабатываются не так хорошо, как могли бы. Исключения могут переопределять друг друга, и мы можем потерять ценную информацию в возникающих трассировках стека. Вы могли бы написать код, чтобы справиться с этим но это сложно и уродливо, поэтому никто так не писал.
Итак, в Java 7 мы получили лучший ответ – попробуйте с ресурсами. С помощью этой конструкции любой класс, реализующий Автоматически закрываемый
может быть обработан Java. Таким образом, приведенный выше пример выглядит следующим образом:
try(InputStream input = new FileInputStream("file"); OutputStream output = new FileOutputStream("other")) { // do work }
Это намного проще. Он также обрабатывает намного больше, чем мы обрабатывали в нашем предыдущем примере. На самом деле код остается не таким. Приведенный выше код преобразуется компилятором в гораздо более подробный результат. Давайте взглянем:
InputStream input = new FileInputStream("file"); Throwable var2 = null; try { OutputStream output = new FileOutputStream("other"); Throwable var4 = null; try { //do work } catch (Throwable var27) { var4 = var27; throw var27; } finally { if (output != null) { if (var4 != null) { try { output.close(); } catch (Throwable var26) { var4.addSuppressed(var26); } } else { output.close(); } } } } catch (Throwable var29) { var2 = var29; throw var29; } finally { if (input != null) { if (var2 != null) { try { input.close(); } catch (Throwable var25) { var2.addSuppressed(var25); } } else { input.close(); } } }
Ух ты! Это стало довольно напряженным. Но если вы проанализируете его, вы увидите, что он выполняет работу, на которую мы надеялись, при более полной обработке исключений.
Последняя мысль. В предыдущем посте Я упомянул инструмент Ломбок . Я очень думаю, что это хороший инструмент. Внутри мешка с трюками Ломбока есть аннотация @Очистка
. Похоже, он сделает что-то очень похожее на описанное выше. Так что же отличает этих двоих? Хотя правильно, что они делают похожие вещи, они немного отличаются. Главное отличие заключается в том, что @Cleanup
просто записывает комбинации try-finally, как мы делали выше, но не выполняет никакой магии, обрабатывая обработку исключений. Таким образом, в то время как @Cleanup
обеспечивает нам безопасность блока finally, мы теряем специализированную обработку исключений.
Итак, вот оно у вас. Используйте “попробуй с ресурсами”. Это проще, чище, безопаснее, это действительно место, где я не вижу много недостатков.
Эффективный обзор Java (Серия из 79 частей)
Оригинал: “https://dev.to/kylec32/effective-java-tuesday-prefer-try-with-resources-2om9”