Проблема с "областями видимости" переменных в блоках try catch в Java - PullRequest
20 голосов
/ 18 мая 2010

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

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.
    }       
}

Спасибо

Ответы [ 3 ]

40 голосов
/ 18 мая 2010

Потому что он объявлен в блоке 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 голосов
/ 16 мая 2017

Чтобы обновить этот ответ после выпуска 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, нажмите здесь

1 голос
/ 18 мая 2010

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

Определить br за пределами блока try.

...