2012-05-01 94 views
0

我有一些關於java定稿的問題。 例如,我有一個FileHelper類,並且此類與讀取文件,寫入文件等相關聯。 現在我的問題是,我有一個方法writeFile()在FileHelper類。現在如果我想關閉該文件 應該重寫finalize()方法並關閉文件,或者我可以關閉writeFile()方法內的文件本身?哪種方法是正確的?我已經將我的File變量聲明爲一個成員變量。如果重寫是一個糟糕的主意,那麼爲什麼我們要重寫finalize()方法?哪種情況?我讀過很多文章,他們說要關閉文件,字體等系統資源。java finalization疑惑

回答

3

最好的做法是儘快關閉文件。如果您有FileHelper靜態方法(假設你的助手是一堆靜態「幫手」的方法),我會關閉該文件內

static void writeFile(String fileName, String text) { // Exception 
// Open file here 
// write text 
// close it 
} 

壓倒一切的finalize的目的是釋放例如在非託管資源以防萬一有人忘記這樣做。如果有人用你的助手這樣

FileHelper fileHelper = new FileHelper(file); 
fileHelper.writeFile(text); 
// forgot to fileHelper.close(); 

可以去覆蓋的最終化和調用close()時,GC運行裏面的文件將被關閉。問題:

  • 正如我提到的早期版本的文件,應儘快關閉(但不是越快;))
  • 這是不確定的(沒有身體知道什麼時候GC會開始)
  • 這應該只用於以防止調用者忘記關閉文件的情況
+0

要添加一些顏色評論,覆蓋最終化也會使GC更昂貴(您的對象將通過至少兩次GC遍歷),並且JVM沒有義務以任何種類的及時方式調用該方法 - 甚至根本就不是。有關Finalize和GC的各種文章,所有這些強烈建議遠離重寫該方法。 – yshavit

+0

當然,但這是一個角落案件。當我執行IO操作時,我不會擔心GC開銷 - 數量級降低。有點比較我的滾軸葉片和噴氣機。 –

+0

毫無疑問,但我正在詳細闡述OP是否正在考慮在非IO類中使用該方法。想象一下,當我們談論這個問題時,我會提及它。 – yshavit

0

重寫finalize()不是一個好習慣。我會在代碼中完成它。

1

在幾乎所有情況下使用終結器是一個壞主意。 Java規範聲明,不能保證終結器能夠運行。即使他們這樣做,你也無法控制何時會發生這種情況。

使用終結器作爲主要的關閉文件的機制總是一個壞主意。爲什麼?因爲如果GC長時間不運行,應用程序可能會耗盡文件描述符,並且文件打開嘗試將開始失敗。

處理打開的流的最好方法是將它們保存在本地變量和參數中,並使用try { ...} finally來確保它們在完成時始終關閉。或者在Java 7中,使用新的「try with resource」語法。

如果您需要將流放入成員變量中,您可能應該讓父類實現一個關閉流的方法close(),並使用try { ...} finally來確保父類的實例關閉。


還應該指出的是,使用終結器來關閉「丟失」流是沒有意義的。使用外部資源需要關閉的流類已經具有完成此操作的終結器。

1

只有當Java垃圾收集器將要回收對象時,纔會調用finalize()方法。在finalize方法中釋放文件句柄是一個不好的做法。

它可能導致java.io.IOException:太多打開的文件,因爲無法保證垃圾回收器何時運行。

更好的選擇是關閉finally塊中的文件讀寫器對象。因爲它保證運行。

finally { 
    // Always close input and output streams. Doing this closes 
    // the channels associated with them as well. 
    try { 
    if (fin != null) 
     fin.close(); 
    if (fout != null) 
     fout.close(); 
    } catch (IOException e) { 
    }} 

fin和fout是FileInputStream和FileOutputStream對象。