避免使用finalize

閱讀經(jīng)典——《Effective Java》03

Java語言包中的Object類是所有類的祖先身腻。該類提供了諸如equals产还、hashCode、toString嘀趟、clone脐区、finalize等方法。本文重點(diǎn)討論finalize方法她按,其余將在后面文章中陸續(xù)出現(xiàn)牛隅。

finalize方法

Java文檔對(duì)finalize方法的解釋如下。

當(dāng)對(duì)象不再擁有可到達(dá)的引用時(shí)酌泰,垃圾回收器在回收該對(duì)象的空間前調(diào)用它的finalize方法媒佣。子類可在該方法中釋放占用的系統(tǒng)資源或執(zhí)行其它清理工作。

通常陵刹,我們會(huì)用finalize方法關(guān)閉已經(jīng)打開的文件默伍,但是請(qǐng)注意,這是嚴(yán)重錯(cuò)誤授霸!

finalize方法的缺點(diǎn)在于不保證會(huì)被及時(shí)的執(zhí)行巡验,甚至根本不保證一定會(huì)執(zhí)行。很多時(shí)候直到程序終止仍然有不可達(dá)對(duì)象的finalize方法沒有被執(zhí)行碘耳。因此,在finalize中關(guān)閉文件很可能失敗框弛。

另外辛辨,System.gc()System.runFinalization()只是增加finalize被執(zhí)行的機(jī)會(huì)。唯一聲稱保證finalize方法在程序終止前執(zhí)行的是System.runFinalizersOnExitRuntime.runFinalizersOnExit瑟枫。但它們有致命的缺陷斗搞,已經(jīng)被廢棄了。

finalize中拋出的異常會(huì)被忽略慷妙,以至于程序員無法得知它是否成功執(zhí)行僻焚。

finalize會(huì)導(dǎo)致嚴(yán)重的性能損失(在原書作者的機(jī)器上,有finalize方法時(shí)創(chuàng)建和銷毀對(duì)象慢了大約430倍)膝擂。

因此虑啤,鑒于finalize方法有如此多的缺點(diǎn)隙弛,我們大部分時(shí)候應(yīng)當(dāng)避免使用。但仍有兩種合理用法狞山。

用途一:配合顯式終止方法

仍然是關(guān)閉文件的問題全闷,正確的做法是提供一個(gè)顯式終止方法,通常稱為close萍启,并要求客戶端程序手動(dòng)調(diào)用总珠。該方案的典型例子是InputStreamOutputStream勘纯、java.sql.Connection局服,這些類都提供了close方法以關(guān)閉相應(yīng)的文件或數(shù)據(jù)庫連接。

但是一些不靠譜的程序員通常會(huì)忘記調(diào)用close方法驳遵,因此可以在finalize中再次檢查并調(diào)用close方法腌逢,以降低資源泄漏的可能性。(注意超埋,由于finalize并不可靠搏讶,該方案只能降低資源泄漏的可能性而無法完全消除。)在InputStream霍殴、OutputStream媒惕、java.sql.Connection這些類中也的確是這樣做的,大家可以自己查看源碼来庭。

用途二:終結(jié)方法守衛(wèi)者

如果子類打算重寫父類的finalize方法妒蔚,我們推薦以下面的方式重寫。這樣做可以保證即使子類的終結(jié)過程拋出異常月弛,父類的finalize方法也會(huì)得到執(zhí)行肴盏。

@Override
protected void finalize() throws Throwable {
  try {
    //Finalize subclass state
  } finally {
    super.finalize();
  }
}

但是,假如子類沒有在重寫的finalize方法中調(diào)用super.finalize()帽衙,那么父類的finalize方法將永遠(yuǎn)不能得到調(diào)用菜皂。站在父類的角度上,要想防范這樣粗心或者惡意的子類厉萝,可以使用終結(jié)方法守衛(wèi)者恍飘。

終結(jié)方法守衛(wèi)者是在父類中的一個(gè)匿名內(nèi)部類實(shí)例,該內(nèi)部類覆寫finalize方法谴垫,并在其中做父類需要的終結(jié)操作章母。

public class Foo {
  private final Object finalizerGuardian = new Object() {
    @Override
    protected void finalize() throws Throwable {
      //Finalize outer Foo object
    }
  };
  //...
}

現(xiàn)在,即使Foo的子類覆寫了finalize方法翩剪,也不會(huì)影響Foo的終結(jié)操作乳怎,因?yàn)?code>finalizerGuardian一直存在。當(dāng)子類對(duì)象不可達(dá)時(shí)前弯,finalizerGuardian同樣不可達(dá)蚪缀,它們都會(huì)進(jìn)入垃圾回收器的回收隊(duì)列秫逝。因此可以保證父類的終結(jié)操作不被忽略。

關(guān)注作者文集《Effective Java》椿胯,第一時(shí)間獲取最新發(fā)布文章筷登。

參考資料

Java終結(jié)方法的使用(終結(jié)守衛(wèi)者) SamXCode
What's the behaviors of fields when finalize an object? jinge
Java將棄用finalize()方法? Ben Evans

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末哩盲,一起剝皮案震驚了整個(gè)濱河市前方,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌廉油,老刑警劉巖惠险,帶你破解...
    沈念sama閱讀 216,470評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異抒线,居然都是意外死亡班巩,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門嘶炭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來抱慌,“玉大人,你說我怎么就攤上這事眨猎∫纸” “怎么了?”我有些...
    開封第一講書人閱讀 162,577評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵睡陪,是天一觀的道長寺渗。 經(jīng)常有香客問我,道長兰迫,這世上最難降的妖魔是什么信殊? 我笑而不...
    開封第一講書人閱讀 58,176評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮汁果,結(jié)果婚禮上涡拘,老公的妹妹穿的比我還像新娘。我一直安慰自己须鼎,他們只是感情好鲸伴,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著晋控,像睡著了一般。 火紅的嫁衣襯著肌膚如雪姓赤。 梳的紋絲不亂的頭發(fā)上赡译,一...
    開封第一講書人閱讀 51,155評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音不铆,去河邊找鬼蝌焚。 笑死裹唆,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的只洒。 我是一名探鬼主播许帐,決...
    沈念sama閱讀 40,041評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼毕谴!你這毒婦竟也來了成畦?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,903評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤涝开,失蹤者是張志新(化名)和其女友劉穎循帐,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體舀武,經(jīng)...
    沈念sama閱讀 45,319評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拄养,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了银舱。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瘪匿。...
    茶點(diǎn)故事閱讀 39,703評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖寻馏,靈堂內(nèi)的尸體忽然破棺而出棋弥,到底是詐尸還是另有隱情,我是刑警寧澤操软,帶...
    沈念sama閱讀 35,417評(píng)論 5 343
  • 正文 年R本政府宣布嘁锯,位于F島的核電站,受9級(jí)特大地震影響聂薪,放射性物質(zhì)發(fā)生泄漏家乘。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評(píng)論 3 325
  • 文/蒙蒙 一藏澳、第九天 我趴在偏房一處隱蔽的房頂上張望仁锯。 院中可真熱鬧,春花似錦翔悠、人聲如沸业崖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽双炕。三九已至,卻和暖如春撮抓,著一層夾襖步出監(jiān)牢的瞬間妇斤,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留站超,地道東北人荸恕。 一個(gè)月前我還...
    沈念sama閱讀 47,711評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像死相,于是被迫代替她去往敵國和親融求。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • 一算撮、終結(jié)方法VS析構(gòu)器 熟悉C++的都知道生宛,析構(gòu)器是用來回收一個(gè)對(duì)象所占用資源的常規(guī)方法,是構(gòu)造器所必需的對(duì)應(yīng)物钮惠。...
    真愛也枉然閱讀 482評(píng)論 0 0
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法茅糜,類相關(guān)的語法,內(nèi)部類的語法素挽,繼承相關(guān)的語法蔑赘,異常的語法,線程的語...
    子非魚_t_閱讀 31,622評(píng)論 18 399
  • 終結(jié)方法的缺點(diǎn) 終結(jié)方法(finalizer)是不可預(yù)測的预明,也是很危險(xiǎn)的缩赛。使用終結(jié)方法會(huì)導(dǎo)致行為不穩(wěn)定、降低性能撰糠,...
    每天學(xué)點(diǎn)編程閱讀 364評(píng)論 0 1
  • 這兩天工作太忙了酥馍,實(shí)在沒時(shí)間寫英語干貨文章。 不過明天的文章是關(guān)于如何提高英語溝通技巧的阅酪,大家可以好好看看旨袒。文章比...
    Freedom_Pursuer閱讀 239評(píng)論 7 2
  • 野外逢迎少,柴門落葉稠术辐,人閑不掃室砚尽,客到始梳頭。 且為烹茶坐辉词,還因看竹留必孤,登臨如有興,更上水邊樓瑞躺。 ——明·何景明...
    NuIl閱讀 407評(píng)論 1 0