Java中try catch块中变量"范围"的问题

dev*_*ium 21 java try-catch

任何人都可以解释为什么在最后几行中,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.
    }       
}
Run Code Online (Sandbox Code Playgroud)

谢谢

Art*_*cto 41

因为它在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) {}
    }       
}
Run Code Online (Sandbox Code Playgroud)

  • 也许你,吞噬了极乐世界,省略了`= null;`这是很难接受的,因为当你省略它时,你会得到消息'br可能是null /不被初始化',这意味着,它是null,但如果你明确地写它,它是默默接受的.非常保姆,但意思是,imho. (2认同)

Top*_*Pug 6

自 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();
    } 
}
Run Code Online (Sandbox Code Playgroud)

请注意,现在您甚至不需要担心变量的范围,因为不需要调用 .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
   }
}
Run Code Online (Sandbox Code Playgroud)

如果您需要有关使用 try-with-resources 的更多说明,请单击此处