Ресурс ресурса Try-with-resources

В конструкторе try -with-resources Java 7 я могу объявить ресурс в инструкции try, и он будет закрыт автоматически, когда он выходит за рамки.

Однако я не вижу никаких указаний на объем ресурса, доступный. В частности, доступен ли он в блоках catch/finally блока try, где он объявлен?

Я пробовал следующее в Eclipse Kepler, но это создавало смешанное впечатление:

Переменная ресурса доступна в Content Assist (Code Completion):

Content Assist suggests resource

Quick Fix предлагает перейти на переменную ресурса, но это рекурсивно создает ту же проблему, которую она пытается исправить:

Redundant suggestion in Quick Fix

Я хотел бы знать, что такое правильное ограничение области видимости, прежде чем поднимать ошибку в Eclipse Bug Tracker.

Ответ 1

Этот синтаксис называется Extended try-with-resources

По JLS:

try ResourceSpecification
    Block
Catchesopt
Finallyopt

Будет переведено на:

try {
    try ResourceSpecification
        Block
}
Catchesopt
Finallyopt

Итак, в вашем примере ваш ресурс будет ограничен внутренним блоком try, поэтому недоступен для внешнего try/catch/finally.

EDIT:

В моем вопросе нет встроенных блоков try

Явным образом добавив блок catch/finally в ваш код, вы вводите вложенные блоки try.

Ответ 2

Правильное ограничение видимости ограничено частью декларации (...) и фактическим блоком try.

JLS утверждает

Объем переменной, объявленной в ResourceSpecification try-with-resources (§14.20.3) из декларации вправо над остальной частью ResourceSpecification и весь блок try, связанный с оператором try-with-resources.

Итак, из точки она объявляется в ResourceSpecification (...) от try вперед до окончательного закрытия } скобки try Block.

TryWithResourcesStatement:
    try ResourceSpecification Block Catchesopt Finallyopt

ResourceSpecification:
    ( Resources ;opt )

Resources:
    Resource
    Resource ; Resources

Resource:
    VariableModifiersopt Type VariableDeclaratorId = Expression

Ответ 3

В дополнение к ответу @Nambari:

Оператор try-with-resources может иметь catch и, наконец, блокировать только как обычный пример заявления. В заявлении try-with-resources любой catch или finally выполняется после того, как объявленные ресурсы были замкнутый.

Это в значительной степени объясняет поведение, ваш ресурс выходит из области видимости в вашем явном блоке catch/finally.

Ссылка

Ответ 4

Обновление с 2017 года после выпуска Java 9

Теперь с Java 9 мы имеем больше синтаксического сахара, и у нас может быть ресурс, объявленный вне блока try-catch, но все же обработанный должным образом. Вот почему с Java 9 улучшена поддержка Try-With-Resources, введя новый синтаксис:

InputStream stream = new MyInputStream(...)
try (stream) {
   // do something with stream being sure that is going to be closed at the end
} catch(IOException e) {
   // you can surely use your resource here
}

Обратите внимание, что этот синтаксис приведет к ошибке времени компиляции для Java версии 8 или младшего

Это более "естественный" способ записи, хотя в большинстве случаев нам не нужен ресурс, выходящий за рамки блока try. Единственное ограничение состоит в том, что переменная считывателя должна быть эффективной или окончательной.

В любом случае с этим синтаксисом вы можете использовать свой ресурс также в блоке catch и finally