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

Почему для try-with-resource требуется локальная переменная?

Что касается моего вопроса Любой риск в обертке AutoCloseable для java.util.concurrent.locks.Lock?, мне интересно, почему trh try-with-resource требует локальная переменная.

Мое текущее использование выглядит следующим образом:

try (AutoCloseableReentrantReadWiteLock.Lock l = _lock.writeLock()) {
    // do something
}        

Переменная l не используется внутри блока try и только загрязняет пространство имен. Из того, что я помню, аналогичный оператор C# using не требует локальной именованной переменной.

Есть ли какая-то причина, по которой невозможно было поддерживать следующее: с анонимной локальной переменной, которая закрыта в конце блока try?

try (_lock.writeLock()) {
    // do something
}        
4b9b3361

Ответ 1

Ссылка в комментарии от @McDowell показывает правильный ответ в комментарий к сообщению в блоге Джо Дарси, который вел спецификация технологии Java, в которой представлен оператор try-with-resources:

Назад в JDK 7, мы начали с конструкции try-with-resources как что позволило использовать общее выражение для ресурса, включая вызов метода. Однако группа экспертов, найденная ранним проект обзора (http://jcp.org/aboutJava/communityprocess/edr/jsr334/index.html), который

"Возможное изменение в будущем [в try-with-resources statemenbt] отказ от поддержки ресурса, который будет указан как общий Expression. Нетривиальные спецификации и сложности реализации возникают из-за возможности использования общего выражения в качестве ресурса. ограниченное выражение, которое может быть идентификатором или PrimaryNoNewArray может быть достаточным. Даже более строгое ограничение просто позволяя идентификатор может обеспечить почти все дополнительные полезность разрешения полного выражения (заставляя объявление новая переменная ресурса) при значительно меньшей предельной реализации и влияние спецификации.

К концу JDK 7 мы хотели, чтобы было новое объявление переменной для ресурса или существующей окончательной/эффективной конечной переменной. Мы только успел предоставить первую в 7; в 9, мы предоставляем последний тоже.

Ответ 2

Среди вариантов использования, которые они рассматривали, большинству понадобится доступ к ресурсу внутри блока, например, открыть файл - прочитать/записать файл - закрыть файл. Они не приняли бы это дизайнерское решение, если бы подумали, что существует много вариантов использования, когда локальная переменная не используется.

Что касается того, почему Lock не автозастраивается, я думаю, что Дуг Ли не слишком озабочен синтаксическим вопросом, он сосредоточен на решении трудной проблемы. Другие могут всегда добавлять синтаксический сахар поверх своих утилит.

В ожидании, попробуй-с-ресурсом, вероятно, выпадет из моды, заменив лямбдой. Например

lock.withLock( ()->{ execute-while-holding-the-lock; } );

Ответ 3

Насколько мне жаль, этого не произошло, обоснование этого заключается в том, что try-with-resources предназначено исключительно для операций над элементом, который должен быть удален. Для этого требуется именованная переменная, потому что она ожидает, что вы сделаете что-то с этой переменной, пока находитесь внутри блока. Я думаю, это похоже на компилятор, говорящий: "Если вы не планируете фактически использовать ресурс, почему вы пытаетесь использовать ресурсы?"

Теперь мы с вами хорошо знаем, что мы не хотим использовать ресурс, скорее, мы просто хотим убедиться, что он закрыт, когда мы закончили с ним, поэтому у нас нет разработчиков, которые собираются блокировать система. Но, как и многие другие, они должны были принимать дизайнерские решения и быть в меньшинстве, мы не получили эту функцию.

Ответ 4

Я думаю, что невозможность использования локальной переменной была триггером для try-with-resource.

До java 1.7 вам нужно было написать что-то вроде этого:

InputStream in = null;
try {
    in = ....;
} finally {
    if (in != null) {
        in.close();
    }
}

Здесь есть два недостатка:

  • Блок
  • finally раздражает и должен быть нулевым для каждого закрывающего ресурса
  • Мы должны объявлять ресурсы за пределами блока, чтобы иметь доступ к ним в блоке finally. Поэтому мы расширяем область применения переменных, которая является плохой практикой.

Синтаксис Try-with-resource разрешает обе проблемы:

  • finally блок вообще не нужен.
  • Переменная ресурса остается доступной только в блоке try, т.е. где она должна быть известна.

Вот почему закрываемый ресурс должен быть локальным. В противном случае одним из основных недостатков синтаксиса try-with-resource является "отключено".