Почему требуется объявление в Java try-with-resource - программирование
Подтвердить что ты не робот

Почему требуется объявление в Java try-with-resource

Java7 try-with-resources - это здорово и все, но я не могу оборачивать себя тем, почему требуется включать объявление ресурса в оператор try. Моя кишка говорит, что должно быть возможно:

CloseableResource thing;
try (thing = methodThatCreatesAThingAndDoesSomeSideEffect()) {
    // do some interesting things
}
thing.collectSomeStats();

Увы, это приводит к синтаксической ошибке (критически ожидая ;). Перемещение определения/объявления типа в оператор try работает, что, конечно же, перемещает предмет в соответствующую область. Я могу понять, как обойти это, когда я хочу больше от моего AutoClosable, чем закрываться, меня интересует, почему компилятор требует его так.

4b9b3361

Ответ 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();

Надеюсь, что это поможет.