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

Проблема с "областями" переменных в блоках catch try в Java

Может ли кто-нибудь объяснить мне, почему в последних строках br не распознается как переменная? Я даже попытался поставить br в try clause, установив его как final и т.д. Это связано с тем, что Java не поддерживает закрытие? Я на 99% уверен, что аналогичный код будет работать на С#.

private void loadCommands(String fileName) {
    try {
        final BufferedReader br = new BufferedReader(new FileReader(fileName));

        while (br.ready()) {
            actionList.add(CommandFactory.GetCommandFromText(this, br.readLine()));
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (br != null) br.close(); //<-- This gives error. It doesn't
                                    // know the br variable.
    }       
}

Спасибо

4b9b3361

Ответ 1

Потому что он объявлен в блоке try. Локальные переменные, объявленные в одном блоке, недоступны в других блоках, кроме тех, которые содержатся в нем, то есть переменные выходят из области действия, когда их блок заканчивается. Сделайте это:

private void loadCommands(String fileName) {
    BufferedReader br = null;
    try {
        br = new BufferedReader(new FileReader(fileName));

        while (br.ready()) {
            actionList.add(CommandFactory.GetCommandFromText(this, br.readLine()));
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (br != null) try { br.close(); } catch (IOException logOrIgnore) {}
    }       
}

Ответ 2

br определяется в блоке try, поэтому он не находится в области в конечном блоке.

Определите br вне блока try.

Ответ 3

Чтобы обновить этот ответ после выпуска Java 7 и 8:

Во-первых, если вы объявите переменную внутри традиционного блока try {}, у вас не будет доступа к этой переменной за пределами этого блока try.

Теперь, начиная с Java 7, вы можете создать Try-With-Resources, который может сократить ваш код, он удалит вашу проблему с "областью", а также автоматически закрывает ресурсы для вас! Хит-трик в этой ситуации;)

Эквивалентный код с Try-With-Resources:

private void loadCommands(String fileName) {
    try (BufferedReader br = new BufferedReader(new FileReader(fileName))){
        while (br.ready()) {
            actionList.add(CommandFactory.GetCommandFromText(this, br.readLine()));
           }
    } catch (FileNotFoundException e) {
          e.printStackTrace();
    } catch (IOException e) {
          e.printStackTrace();
    } 
}

Обратите внимание: теперь вам даже не нужно беспокоиться об объеме переменной, так как нет необходимости вызывать .close(), она автоматически выполняется для вас!

Любой класс, реализующий интерфейс AutoClosable, может использоваться в блоке Try-With-Resources. В качестве краткого примера я оставлю это здесь:

public class Test implements AutoCloseable {

public static void main(String[] args) {
    try (Test t = new Test()) {
        throw new RuntimeException();
    } catch (RuntimeException e) {
        System.out.println(e);
    } catch (Exception e) {
        System.out.println(e);
    }
    System.out.println("The exception was caught and the program continues! :)");
  }

@Override
public void close() throws Exception {
    // TODO Auto-generated method stub
   }
}

Если вам нужно больше объяснений при использовании try-with-resources, нажмите здесь