Эффективный обзор 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”