2010-05-18 34 views
20

任何人都可以解释为什么在最后一行中,br不被识别为变量?我甚至尝试把try clause中的br设置为final等。这与Java不支持关闭有什么关系?我有99%的自信类似的代码可以在C#中工作。Java中try catch块中变量的“范围”问题

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

C#有一个'using'关键字,像一个for循环,可以:作为一个简单的例子,我会离开这里这个你可以定义一个受随后范围限制的变量。 Java没有。 – Yishai 2010-05-18 02:00:44

+0

顺便说一句:我不会在这里做'e.printStackTrace()'。您的程序可能会继续运行,并有可能为空的操作列表。你不想那样做。只需通过并让您的应用程序退出或停止并显示一条明确的错误消息,以便最终用户可以采取相应的措施。 – BalusC 2010-05-18 02:32:34

+0

我仍然不知道如何处理Java中的异常。在C#中,我会把它放在堆栈中,但如果我想这样做,我必须在这个函数和任何调用这个函数的函数中放置一个throws声明。它是一个PITA。 – 2010-05-18 02:47:06

回答

40

因为它在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) {} 
    }  
} 
+0

我几乎确定我在这里尝试了相同的代码,但没有奏效。非常感谢! – 2010-05-18 02:11:20

+0

好,太好了。现在它不会让我做br.close()而不将它包围在另一个try catch块中。我应该做些什么? – 2010-05-18 02:12:42

+0

只是把那个另一个try/catch块放在;) – BalusC 2010-05-18 02:16:31

1

BR在try块定义,所以它不是在范围内的finally块。

在try块外定义br。

0

要更新这个答案,因为Java 7的& 8版本:

首先,如果你申报了传统的尝试{}块中的变量,你将不能访问该变量的外该尝试阻止。

现在自Java 7以来,您可以创建一个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 
    } 
} 

试穿与资源单击here