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

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

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

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

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

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

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

person Miserable Variable    schedule 16.05.2013    source источник
comment
Это решается в Java 9. См. JDK-8068949.   -  person McDowell    schedule 09.02.2015
comment
@McDowell Java 9 обращается к текущему поведению, которое требует определения новой переменной, позволяя использовать существующую эффективную конечную переменную. Из вашей ссылки не видно, что Java 9 будет поддерживать автоматически закрывающиеся ресурсы без видимого идентификатора. (обсуждается здесь.)   -  person William Price    schedule 25.03.2017


Ответы (4)


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

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

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

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

person Zero3    schedule 12.01.2016
comment
java9 по-прежнему не поддерживает случай OP. - person ZhongYu; 13.01.2016

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

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

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

lock.withLock( ()->{ execute-while-holding-the-lock; } );
person ZhongYu    schedule 16.05.2013
comment
+1 за использование ламды. Остальное спекулятивно. Хотя, наверное, правильно, меня больше интересует, если есть причины, по которым это невозможно. - person Miserable Variable; 16.05.2013
comment
уверен, что это можно сделать, это просто больше работы, они не думали, что это того стоит. - person ZhongYu; 16.05.2013
comment
ИМХО, это злоупотребление лямбдами. Нет преимуществ, и это затрудняет чтение кода. Не делай этого. - person Erich Schubert; 07.11.2014
comment
Они бы не приняли такое дизайнерское решение ...: Да, они бы приняли. Из-за нехватки времени. Смотрите мой ответ. - person Zero3; 13.01.2016
comment
Идея с lamda-выражениями хороша, но имеет несколько серьезных проблем: 1) пошаговое выполнение кода в отладчике становится проблемой 2) иерархия вызовов загромождена lamda-вызовами 3) завершение кода внутри lamdas в настоящее время неоптимально (по крайней мере, в Затмение Неон). - person Alan47; 14.11.2016
comment
Невозможно обобщить проверенные типы исключений с помощью интерфейсов, совместимых с SAM, поэтому такой вид использования никогда полностью не заменит try-with-resources, то есть вы не можете получить доступ к определенному типу проверенного исключения, возвращаемому телом выполнения. - person jkschneider; 24.10.2017
comment
@jkschneider - Полагаю, в принципе, вывод типов мог бы дать объединение типов исключений E1 | E2 ... для некоторых <T extends Throwable>. Но в любом случае, в настоящее время прозрачность исключений не поддерживается через лямбда. - person ZhongYu; 27.10.2017
comment
@ZhongYu, это хорошо объясняет подводные камни этой попытки: dzone.com/articles/ - person jkschneider; 28.10.2017

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

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

person corsiKa    schedule 27.06.2013
comment
Я использую ресурс - из-за его побочных эффектов в его <init>() и close() - person Miserable Variable; 27.08.2013
comment
Но вы не используете его внутри блока, что является основным вариантом использования try-with-resources. Меня это тоже расстраивает, но так оно и есть. Вы можете сэкономить немного недвижимости, import static выбрав свой класс Lock. - person corsiKa; 27.08.2013
comment
Есть много причин не использовать ресурс явно внутри блока, например, это может быть блокировка; или хранится в ThreadLocal. - person Stefan Reich; 02.12.2017
comment
Я полностью согласен с тобой, Стефан. Как я уже сказал, меня это тоже расстраивает. Казалось бы, init и close не рассматриваются в блоке разработчикам этой функции. - person corsiKa; 02.12.2017
comment
это было абсолютно ужасное решение. try with resources может использоваться для закрытия блоков. Такая близорукость - person Enerccio; 13.05.2021

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

До java 1.7 вам приходилось писать что-то вроде этого:

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

Здесь есть 2 минуса:

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

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

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

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

person AlexR    schedule 16.05.2013
comment
Вы указали вескую причину для объявления allow в try-with-resources. OP спрашивает, почему это требуется. - person Andy Thomas; 16.05.2013
comment
Основная мотивация явно состоит в том, чтобы избежать большого количества шаблонов и предоставить программисту готовое решение довольно сложной и тонкой проблемы. Думаю, проблема в размахе макс. 10% от всей истории. - person Marko Topolnik; 16.05.2013
comment
Не могли бы вы отредактировать свой ответ? В его нынешнем виде он не отвечает на мой вопрос - person Miserable Variable; 22.10.2013