2011-10-04 80 views
5

大部分時間裏,我看到了最後使用的塊的唯一的事情是一樣的東西爲什麼我需要最終使用來關閉資源?

FileInputStream f; 
try{ 
    f= new FileInputStream("sample.txt"); 
    //something that uses f and sometimes throws an exception 
} 
catch(IOException ex){ 
    /* Handle it somehow */ 
} 
finally{ 
    f.close(); 
} 

我的問題是,如果f的範圍與封閉塊,爲什麼我們需要關閉它在最後結束?

+0

對你而言,'f'的作用域並不以try-block結束 –

+0

@Oli Charlesworth:這顯然是一個可讀的例子。 –

+0

創建文件引用不會引發異常(或創建文件句柄),以備將來參考。 –

回答

18

因爲垃圾回收是而不是與資源清理一樣。

例如,如果您有超出範圍的JDBC連接對象,則沒有信號發送到數據庫服務器以指示不再需要打開的遊標和連接。如果沒有這些信息,您最終會耗盡可用的遊標和連接數量。

與文件句柄和任何其他資源一樣。自己清理。

+2

當然可以。但爲什麼'最後'? – 2011-10-04 18:00:12

+5

因爲即使引發異常,finally塊中的代碼也能保證執行。 – duffymo

+1

@Joe很好的例子。但是如果你有一個拋出異常的catch塊,那麼永遠不要在finally塊中返回一些東西。在這種情況下,你的異常將永遠不會被拋出......我學會了這一個艱難的方式;-) – Cygnusx1

6

那麼你已經給出了一個不好的例子 - 我懷疑你的意思是像FileInputStream - 但基本原因是Java沒有確定性的最終確定。

的範圍變量f與它的(不是try塊)聲明的塊結束,但這並不意味着有一定沒有「活」的對象更多的引用 - 和垃圾收集器既不會最終確定對象,也不會以任何確定性的方式收集垃圾。

除非你想讓資源在任意長度的時間內停留(並且延遲垃圾回收,因爲在內存最終被釋放之前終結器需要額外的一輪迴收),你應該明確地關閉資源。

基本上Java不支持不支持支持RAII的方式與C++相同;你不應該像使用C++一樣使用它。

+0

編輯,以反映你的建議:我只是想出一個Closeable從內存,所以感謝給我一個實際適用:P –

0

原因是,Java不保證一旦對象的特定引用超出了範圍,它就會被垃圾回收。因此,對於引用有限系統資源的對象(如文件描述符),僅等待垃圾回收是不夠的。

但請注意,java.io.File實際上並不是這樣一個對象。

1

因爲終於每次調用,即使你得到一個異常引發。 finally塊可以確保文件/連接將被關閉。

0

最後我們通過try catch來處理異常,最後每次執行block都會阻塞,但是沒有catch的保證,因爲catch塊只有在匹配的參數傳入的異常時才執行。 例如,如果我們已經打開任何數據庫連接,所以我們必須在離開前關閉它,那麼最終必須實施。

相關問題