Проблема с "областями" переменных в блоках 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.
}
}
Спасибо
Ответы
Ответ 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, нажмите здесь