Почему требуется объявление в Java try-with-resource
Java7 try-with-resources - это здорово и все, но я не могу оборачивать себя тем, почему требуется включать объявление ресурса в оператор try
. Моя кишка говорит, что должно быть возможно:
CloseableResource thing;
try (thing = methodThatCreatesAThingAndDoesSomeSideEffect()) {
// do some interesting things
}
thing.collectSomeStats();
Увы, это приводит к синтаксической ошибке (критически ожидая ;
). Перемещение определения/объявления типа в оператор try
работает, что, конечно же, перемещает предмет в соответствующую область. Я могу понять, как обойти это, когда я хочу больше от моего AutoClosable
, чем закрываться, меня интересует, почему компилятор требует его так.
Ответы
Ответ 1
В вашей версии четко не определено, что должно быть закрыто, например
CloseableResource thing;
Parameter a;
try (a = (thing = methodThatCreatesAThingAndDoesSomeSideEffect()).getParameter()) {
также, что делать, если вы пишете
try (12) {
или что-то?
также
CloseableResource thing1 = methodThatCreatesAThingAndDoesSomeSideEffect();
CloseableResource thing2 = methodThatCreatesAThingAndDoesSomeSideEffect();
try(thing1) {
}
почему только закрыть thing1
?
Итак, текущий синтаксис заставляет вас создавать переменную одновременно с открытием закрывающего блока.
ALSO2
CloseableResource thing1 = методThatCreatesAThingAndDoesSomeSideEffect();
try(thing1) {
}
thing1.doSomethingOnClosedResource();
так как thing1
остается.
Ответ 2
Чтение спецификации java Я пришел к такому выводу (хотя это неявно указывает на это):
Они заставляют вас объявлять переменную и добавлять к ней неявное окончание, чтобы убедиться, что вы не можете привязать переменную к чему-то еще.
В этом случае невозможно будет закрыть ресурс, потому что он больше не привязан к переменной.
Пример:
CloseableResource thing;
try (thing = methodThatCreatesAThingAndDoesSomeSideEffect()) {
thing = null;
// thing can't be closed now
}
Они могут заставить вас использовать финал, если его снаружи я предполагаю, но это отвратительно.
Обход проблемы:
Вы можете использовать finally
, если вы хотите получить доступ к объявленному ресурсу:
try (CloseableResource thing = methodThatCreatesAThingAndDoesSomeSideEffect()) {
// do some interesting things
} finally {
thing.collectSomeStats();
}
Имейте в виду, наконец, thing
уже закрыто
Ответ 3
Так как Java 9 вы можете объявить и инициализировать переменную, используемую внутри try-with-resources вне блока. Единственным дополнительным требованием для переменной является то, что она должна быть эффективно окончательной.
Так что теперь можно сделать:
CloseableResource thing = methodThatCreatesAThingAndDoesSomeSideEffect();
try (thing) {
// do some interesting things
}
thing.collectSomeStats();
Надеюсь, что это поможет.