2013-05-16 2 views
49

Со ссылкой на мой вопрос Any risk in a AutoCloseable wrapper for java.util.concurrent.locks.Lock?, мне интересно, почему для trh try-with-resource требуется локальная переменная с именем.Почему для try-with-resource требуется локальная переменная?

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

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

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

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

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

Это [обращение к Java 9] (https://blogs.oracle.com/darcy/entry/concise_twr_jdk9). См. [JDK-8068949] (https://bugs.openjdk.java.net/browse/JDK-8068948). – McDowell

+2

@McDowell Java 9 обращается к текущему поведению, которое требует определения переменной _new_, позволяя использовать эффективную конечную переменную _existing_. Из вашей ссылки не видно, что Java 9 будет поддерживать автоматически закрывающиеся ресурсы _ без видимого идентификатора_. ([Обсуждалось здесь.] (Http://mail.openjdk.java.net/pipermail/core-libs-dev/2015-January/030864.html)) –

ответ

1

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

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

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

Есть 2 недостатков здесь:

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

Try-с-ресурса синтаксис решает обе проблемы:

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

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

+7

Вы указали причину, по которой * разрешить * объявление в попробуйте с ресурсами. ОП спрашивает, почему это * требуется *. –

+0

Основная мотивация явно избегает большого количества шаблонов и предоставляет программисту готовое решение для довольно сложной и тонкой проблемы. Я думаю, что проблема с областью макс. 10% всей истории. –

+0

Извините за недоразумение; Я понимаю, что [ResourceSpecification] (http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.20.3) блок представил локальную переменную, мой вопрос в том, почему должен быть назван. –

8

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

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

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

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

+1 для использования лампы. Остальная часть - спекулятивная. Хотя, вероятно, правильно, меня больше интересует, есть ли причины, по которым это невозможно сделать. –

+0

уверен, что это можно сделать, это просто больше работы, они не думали, что это того стоит. – ZhongYu

+5

ИМХО, это злоупотребление лямбдами. Существует 0 преимуществ, и это делает код более трудным для чтения. Не делай этого. –

4

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

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

+5

I * am * using resource - для его побочных эффектов в '()' и 'close()' –

+0

Но вы не используете его внутри блока, что и является основным вариантом использования try-with-resources. Мне тоже это неприятно, но так оно и есть. Вы можете сэкономить себе некоторую недвижимость путем 'import static'ing вашего класса Lock. – corsiKa

+0

Существует множество причин не использовать ресурс явно внутри блока, например, это может быть блокировка; или удерживается в ThreadLocal. –

11

Ссылка на комментарий по @McDowell показывает правильный ответ в a blog post comment Джо Дарси, который привел the Java Technology Specification, что ввел примерочных с-ресурсов заявление:

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

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

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

+4

java9 все еще не поддерживает случай OP. – ZhongYu

 Смежные вопросы

  • Нет связанных вопросов^_^