2013-07-15 29 views
61

我在期待緩衝的閱讀器和文件閱讀器關閉,並在拋出異常時釋放資源。我是否正確使用Java 7試用資源

public static Object[] fromFile(String filePath) throws FileNotFoundException, IOException 
{ 
    try (BufferedReader br = new BufferedReader(new FileReader(filePath))) 
    { 
     return read(br); 
    } 
} 

但是,是否有要求成功關閉的catch子句?

編輯:

實質上,是在Java 7的上面的代碼等同於下面的Java 6:

public static Object[] fromFile(String filePath) throws FileNotFoundException, IOException 
{ 

    BufferedReader br = null; 

    try 
    { 
     br = new BufferedReader(new FileReader(filePath)); 

     return read(br); 
    } 
    catch (Exception ex) 
    { 
     throw ex; 
    } 
    finally 
    { 
     try 
     { 
      if (br != null) br.close(); 
     } 
     catch(Exception ex) 
     { 
     } 
    } 

    return null; 
} 
+0

再次閱讀您的問題後,我不確定我是否理解得很好。你能解釋一下嗎? – Maroun

+0

嗨。獵豹,我試圖理解你的Java 6第一個catch的作用。 catch(Exception ex){throw ex; }' - 它只是重新拋出異常,它什麼都不做,它可以輕鬆移除而不會受到任何傷害。或者我錯過了什麼? – Sasha

+0

你的語法沒有錯。如果你想了解更多關於試用資源的知識,請查看這篇文章:[Java試用資源](http://programmergate.com/java-try-resources/) –

回答

84

這是正確的,並有一個爲catch子句沒有要求。 Oracle java 7 doc說資源將被關閉不管是否實際拋出異常。

只有當您想對異常做出反應時,才應該使用catch子句。在資源關閉後,將執行catch子句

這裏有一個片段從Oracle's tutorial

下面的示例讀取從文件的第一行。它使用BufferedReader的一個實例來讀取文件中的數據。 BufferedReader中 是程序與 它完成之後,必須關閉資源:

static String readFirstLineFromFile(String path) throws IOException { 
    try (BufferedReader br = 
        new BufferedReader(new FileReader(path))) { 
     return br.readLine(); 
    } 
} // In this example, the resource declared in the try-with-resources statement is a BufferedReader. 

...因爲的BufferedReader實例在 試穿與資源聲明中宣佈,它會被關閉,無論 try語句是否正常或突然完成(由於 方法BufferedReader.readLine拋出IOException)。

EDIT

關於新編輯的問題:

Java 6中的代碼執行和catch事後finally塊。這會導致資源仍可能在catch塊中打開。

在Java 7語法中,之前的資源是之前的catch塊,所以資源在catch塊執行期間已經關閉。這在上面的鏈接中有記錄:

在try-with-resources語句中,在聲明的資源關閉後,任何catch或finally塊都會運行 。

58

在這種特殊情況下,您對資源嘗試的使用可以正常工作,但通常情況下它並不完全正確。你不應該像這樣鏈接資源,因爲它可能會導致不愉快的意外。假設你有一個變量的緩衝區大小:

public static Object[] fromFile(String filePath) throws FileNotFoundException, IOException 
{ 
    int sz = /* get buffer size somehow */ 
    try (BufferedReader br = new BufferedReader(new FileReader(filePath), sz)) 
    { 
     return read(br); 
    } 
} 

假設出了問題,你結束了sz爲負。在這種情況下,您的文件資源(通過new FileReader(filePath)創建)將會關閉而不是

爲了避免這個問題,您應該分別指定每個資源是這樣的:

public static Object[] fromFile(String filePath) throws FileNotFoundException, IOException 
{ 
    int sz = /* get buffer size somehow */ 
    try (FileReader file = new FileReader(filePath); 
     BufferedReader br = new BufferedReader(file, sz)) 
    { 
     return read(br); 
    } 
} 

在這種情況下,即使br初始化仍然失敗file被關閉。你可以找到更多的細節herehere

+0

我試圖理解爲什麼通過'FileReader(filePath)'創建的資源''在sz爲負時拋出'IllegalArgumentException'的情況下不會關閉。不管任何拋出的異常,try-with-resources不會關閉所有'AutoClosable'資源嗎? –

+2

@PrasoonJoshi不,它只爲'try-with-resources'初始化程序中聲明的變量調用'.close()'。這就是爲什麼在這個例子中將它分成兩個聲明的原因。 –

+3

Andrii和@Mario你是對的也是錯的。在第一個例子中,FileReader沒有被try-with-resource邏輯關閉。但是,當BufferedReader關閉時,它也會關閉包裝的FileReader。爲了證明,看看java.io.BufferedReader.close()的來源。因此,應優先考慮來自第一個示例的代碼,因爲它更簡潔。 – jschreiner