2013-07-12 92 views
0

每當我看到Java 6的流處理,它的完成幾乎是這樣的:如何關閉Java流?

public void myMethod() throws Exception 
{ 
    InputStream stream = null; 

    try 
    { 
     stream = connection.openConnection(); 
     ... 
    } 
    finally 
    { 
     if(stream != null) 
     { 
      stream.close(); 
     } 
    } 
} 

但我不明白爲什麼這是必要的。這不會以同樣的方式工作嗎?

public void myMethod() throws Exception 
{ 
    InputStream stream = connection.openConnection(); 

    try 
    { 
     ... 
    } 
    finally 
    { 
     stream.close(); 
    } 
} 

如果openConnection()失敗,那麼stream將不會分配,然後沒有什麼收反正,不是嗎?

+0

它會拋出一個異常,如果connection.openConnection()失敗..你的嘗試,最後沒有任何意義,並假設不失敗,併爲空'流'然後在最後會拋出'NullPointerException' – nachokk

+0

是的,但如果當前與可能觸發IOException的流進行交互,點所隱藏的是什麼。 – Taig

+0

@nachokk但該方法已經拋出異常。另外,可能任何使用'stream'的操作都會拋出一個'Exception'。 –

回答

4

我同意你的意見。

null分配的額外步驟是不必要的和醜陋的。你甚至可以製作最後的stream

我只會寫這樣的東西,如果你有多個資源需要清理(發生在JDBC上),並且你想避免多個嵌套try/finally塊(但通常是I去那些無論如何)。

而對於Java 7,您可以使用try-with構造。

+0

我下面的評論我根本不同意,這樣你就可以失去異常......考慮到某些錯誤發生了業務異常,那麼流爲空...然後stream.close()會拋出NullPointerException,並且你失去了業務異常..使最終的流解決這個例子,但.. – nachokk

+0

Stream.close()'永遠不會被調用,因爲該方法不會在IOException之後終止被扔在第一行。 – Taig

+0

如果業務異常拋出並且'stream'爲null,那麼您不會指定'try block'中發生了什麼,那麼您將失去異常。 – nachokk

0

每當你與構建檢索的InputStream像

InputStream stream = connection.openConnection(); 

有三種可能的結果:要麼該方法返回一個適當的InputStream,或返回null,或者它拋出一個異常。

讓我們看一下所有三種可能性:

1)方法返回一個適當的輸入流。

在這種情況下,try塊會繼續,如果它沒有遇到任何其他問題(也就是異常),它通常會在執行finally塊之後結束。

2)該方法返回null。

在這種情況下,你也應該在try塊內進行空檢查。如果是這樣,你的try塊通常什麼都不做,finally塊也必須有null檢查。否則你的最後一塊會拋出一個NPE。

如果你不防範null返回,你的try塊內的代碼將拋出NPE(我假設在那裏使用流變量)。在這種情況下,finally塊將被執行,並且如果沒有null檢查,將再次拋出NPE。在後一種情況下,只有來自finally塊的第二個NPE實際上被投入給調用者。

3)調用檢索輸入流的方法會引發異常。

在這種情況下,try塊會結束,立即導致finally塊執行,然後該方法會突然結束。但是哪個例外?那要看。

考慮拋出的異常是一個IOException,在大多數情況下拋出異常。首先,變量仍然有空引用!如果沒有空檢查,finally塊會再次拋出一個NPE。在這種情況下,第一個異常(IOE)將被遺忘,因爲只有NPE會傳遞給您的方法調用。這不是一個好主意。

總而言之,空檢查確實是必要的。

現在Java 7帶有try-with-resources構造。這確實是一個更好的機制,因爲它有一個隱式finally塊,其中流被關閉。如果try塊中存在異常,並且隱式finally塊也會引發異常,則將第一個異常(來自try塊內部)傳遞給調用者。這非常合適。語法閱讀起來更好。

+0

2)Java doc中沒有暗示'URL.openConnection()'可能返回'null'。如果它確實會導致失敗,那是真的。 3)請注意,'URL.openConnection()'不是從'try'塊中調用的。所以最後不會執行。該方法的執行將停在第一行並轉發一個'IOException'。 – Taig

+0

是的,你是對的。這兩個代碼片段在技術上都是等同的。事實上,我總是使用靜態工具方法來「靜靜地」關閉一個只使用了一行代碼的流。這是比較常見的,但隨着Java 7的try-with-resources聲明已經過時。 – Seelenvirtuose