2010-05-18 58 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