2015-09-06 101 views
2

使用對象,我們使用3個基本步驟:嘗試與 - 資源的詳細信息

  1. 宣言
  2. 實例化
  3. 初始化

我的問題是關於什麼必須完成的步驟()嘗試使用的一部分,以便自動關閉要創建的資源。 -

實施例1將物體的FileReader被自動在該代碼封閉:

try (BufferedReader br = new BufferedReader(new FileReader(filePath))) 
{ 
//some code; 
} 

實施例2 - 將BUF2是汽車在此代碼封閉:

private static BufferedReader buf1; 

public static void main(String[] args) throws IOException { 
    //some code 
    try (BufferedReader buf2 = buf1) 
    { 

    } 
} 

P.S.有人認爲這個問題是Try With Resources vs Try-Catch的重複。不是這樣。這個問題是關於try-catch和try-with-resources之間的區別。我的問題是關於試用的細節。

+3

聽起來像一個家庭作業問題,但這裏有個提示:try-with-resources *要求*聲明的變量實現'AutoCloseable',並且會在隱式finally塊中調用'close()'。 – Andreas

+1

準備(學習)認證*是作業。谷歌OCPJP甚至會鏈接到「Oracle大學」網站。 ---也許在[The try-with-resources Statement](https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html)上的Java教程的第一段會幫助你。 – Andreas

+1

如果你真的在認真學習Java,你不應該害怕嘗試。創建一個AutoCloseable類。在close()方法中添加一個System.out.println語句。使用上面的代碼而不是BufferedReader。看看是否打印了一些東西。或者只是在BufferedReader.close()中添加一個調試器斷點並查看是否已達到。 –

回答

3

無論何時需要語言相關的細節,最完整的參考是Java語言規範(只是Google它)。對於try -with-resources語句,你可以閱讀section 14.20.3其中指出以下幾點:

try ({VariableModifier} R Identifier = Expression ...) 
    Block 

被翻譯成

{ 
    final {VariableModifierNoFinal} R Identifier = Expression; 
    Throwable #primaryExc = null; 
    try ResourceSpecification_tail 
     Block catch (Throwable #t) { 
     #primaryExc = #t; 
     throw #t; 
     } finally { 
     if (Identifier != null) { 
      if (#primaryExc != null) { 
       try { 
        Identifier.close(); 
       } catch (Throwable #suppressedExc) { 
        #primaryExc.addSuppressed(#suppressedExc); 
       } 
      } else { 
       Identifier.close(); 
      } 
     } 
    } 
} 

在你的第一個例子中,資源RBufferedReader,則IdentifierbrExpressionnew BufferedReader(new FileReader(filePath))。因此,只有BufferedReader在隱含的finally塊中關閉。 finally塊不會在FileReader上調用close,因爲它是而不是資源聲明本身的一部分。但是,這種情況發生在BufferedReader.close()的執行內部調用close包裝的FileReader的方法。所以第一個問題的答案是肯定的,因爲包裝器對象關閉它(遵循常見的理解,即資源在釋放時應該釋放任何包裝的資源),而不是,因爲try與資源。

在第二個例子:

private static BufferedReader buf1; 

public static void main(String[] args) throws IOException { 
    //some code 
    try (BufferedReader buf2 = buf1) 
    { 

    } 
} 

的答案取決於some code。這裏buf2buf1都指向內存中的同一個對象。如果這個「一些代碼」初始化爲buf1某個對象,那麼這個對象將被關閉,因爲buf2也指向它。如果不是,並且buf1爲空(因此buf2爲空),則由於在上面示出的隱含的finally中的空檢查,所以沒有東西會被關閉。

1
  1. FileReader將被關閉。但那不是因爲它在試驗聲明中。這是因爲BufferedReader關閉時,FileReader也會調用close()。舉一個反例,我有一個名爲X的課程,它實現AutoCloseable。並且該類在其構造函數中需要一個Foo對象。所以我寫:

    try (X x = new X(new Foo())) { 
    
    } 
    

Foo被關閉?它甚至沒有執行AutoCloseable

  • 我寫了下面對此進行測試:

    BufferedReader buf1 = null; 
    try (BufferedReader buf2 = buf1) { 
    
    } 
    
  • 和它的工作完全正常,沒有例外!我的猜測是,在try語句結束時,它檢查對象是否爲空。如果不是,則關閉它。所以在這種情況下,因爲buf2爲空,所以不能關閉。