Подтвердить что ты не робот

Почему не пытаться использовать ресурсы с переменными поля?

Это мой первый вопрос о SO, и я смущен, что еще нет похожего вопроса!

Итак, вопрос:

Почему не работает попытка использования ресурсов с переменными поля?

Или другими словами: для чего мне всегда нужна локальная переменная?

Вот пример кода:

public class FileWriteTest {

    public FileWriter file;

    public void workingDemo() {

        try(FileWriter file = new FileWriter(new File("someFilePath")) {
            // do something
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public void notWorkingDemo() {

        file = null;

        try(file = new FileWriter(new File("someFilePath")) {
            // do something
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}

Может кто-нибудь объяснить мне, почему существует это соглашение?

4b9b3361

Ответ 1

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

Кстати, лучший вопрос: почему Java вынуждает нас объявлять локальную переменную, даже если мы не ссылаемся на нее внутри блока. С#, например, не требует этого.

Ответ 2

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

Ответ 3

Раздел 14.20.3 Спецификация языка Java что он будет работать только с локальными переменными.

Почему это? Мое предположение - проверка определенных назначений и escapage (локальная переменная не выходит за рамки другого метода). Поле может быть инициализировано в любом месте класса. Я предполагаю, что, проверяя локальную переменную, ее гораздо проще анализировать.

Ответ 4

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

Итак, IMHO имеет смысл обрабатывать его так, как указано в спецификации.

Ответ 5

Возможно, это связано с согласованностью с языковыми спецификациями. Всякий раз, когда переменная объявляется между двумя скобками, она инкапсулируется внутри и не может быть доступна извне:

anything
{
int var;
}

// cannot access var from here!

Почему shoul try {} является исключением?