2012-10-18 65 views
1

如果我有一個利用IO資源的類,例如磁盤平面文件,DB或某種其他形式的外部資源,那麼關閉這些流的優缺點是什麼/ GC中重載的finalize()方法中的連接?我雖然可以利用現有的JVM GC,並減少依賴客戶端調用類方法(如closeResources())的風險,並編寫類似意大利麪條的try-catches(嵌套try-catches和ifs being我最不喜歡的編程結構)。在重寫的finalize()方法中關閉類IO資源

作爲一個具體的例子,我有一個簡單的文件閱讀包裝。該課程使用String filePath構建,它將該文件讀入List<String[]>。我不想在多個地方關閉BufferedReader,就像在打開文件時出現問題(catch子句)時關閉它一樣,但如果文件讀取正常,也可以關閉它。我想把它放在一個地方並確保無論對象何時獲取GC,它總是關閉。

這種方法是一種很好的做法,還是我試圖在Java的範圍內提供太高水平的便利?

+0

「BufferedReader」變量是構造函數的局部變量,還是其他方法,還是實例變量? –

+0

實例變量 – amphibient

回答

2

這不是一個好主意爲finalize()方法不能保證被調用。

當您的代碼完成後關閉資源會更容易,更好。

如果你不喜歡寫嵌套的try-finally塊來正確關閉資源,使用類似commons-io'sIOUtils默默地關閉資源(或寫自己的簡單UTIL方法默默地關閉它們):

InputStream stream = ...; 
try { 
    ... 
} 
finally { 
    IOUtils.closeQuietly(stream); 
} 
+0

謝謝。我已經逾期看看Apache公用程序。 – amphibient

+2

即時通訊,我會使用谷歌番石榴,因爲它有很多的功能,而不是包括所有的Apache庫。與谷歌番石榴,你可以使用'文件'類 – epoch

0

是,finally塊總是以釋放資源,最好的辦法,如連接,I/O等Sreams

+0

我正在談論重寫Object.finalize(),而不是try/catch的最後一塊 – amphibient

1

當IO資源是一個實例變量,那麼你應該關閉它在finalize()方法。

爲什麼?

  1. 由於beeing一個實例變量,你需要它在一個開放的狀態,因爲有些方法會重複使用它。

  2. 如果關閉它的方法以外完成,那麼你正在創建一個temporal coupling,這意味着該類用戶需要知道他有打電話給在一定的時間順序某些方法,即b之前等。

編輯:

Java文檔指出,垃圾收集器不能保證在任何特定時間運行,將無法運行finalize()只要有任何引用到物體。如果引用逗留,這是一個內存泄漏,一個編程錯誤。 finalize()是資源不是方法本地的最佳選項。如果資源對於某個方法是本地資源,請在try/cath blockfinally末尾將其關閉。

+0

感謝闡述。與@matt b衝突的是,你認爲finalize()保證被執行。我很想知道更多。 – amphibient

+0

基本上,它歸結的是finalize()是否有保證,一般來說它是多麼可靠 – amphibient

+1

@foampile Java文檔指出垃圾收集器不保證在任何**特定時間運行**,並且不會運行'finalize()'只要對象有任何**引用**。如果引用逗留,這是一個內存泄漏,一個編程錯誤。當資源不是方法本地時,'finalize()'是最好的選擇。如果資源是某個方法的本地資源,則在「try/cath塊」的「finally」末尾關閉該資源。 –