第三講-談談 final、finally此改、finalize 有什么不同侄柔?

典型回答:

final 可以用來修飾可變類占调、方法移剪、對象纵苛,分別有不同的意義,final 修飾的 class 代表不可以繼承擴展取试,final 的變量是不可以修改的瞬浓,而 final 的方法是不可以重寫的猿棉。

finally 則是 Java 保證重點代碼一定要被執(zhí)行的一種機制屑咳。我們可以使用 try-finally 或者 try-catch-finally 來進行類似關閉 JDBC 連接兆龙、保證 unlock 鎖等動作紫皇。

finalize 是基礎類 java.lang.Object 的一個方法坝橡,它的設計目的是保證對象在被垃圾收集前完成特定的資源回收计寇。finalize 機制現(xiàn)在已經(jīng)不推薦使用,并且在 JDK 9 起開始被標記為 deprecated。

考點分析

上面的回答主要是從概念的角度出發(fā)的蝶押,其實還可以從很多方面再深入探討,講講對性能苇侵、并發(fā)榆浓、對象生命周期或垃圾收集基本過程等方面的理解撕攒。

推薦使用 final 關鍵字來明確表示我們代碼的語義抖坪、邏輯意圖擦俐,這已經(jīng)被證明在很多場景下是非常好的實踐捌肴,例如:

  • 我們可以將方法或者類聲明為 final藕咏,這樣就可以明確告知別人饥悴,這些行為是不可修改的西设。
  • 使用 final 修飾參數(shù)或者變量贷揽,也可以清楚地避免意外賦值導致的編程錯誤梦碗,甚至印屁,有人明確推薦將所有的方法參數(shù)雄人、本地變量念赶、成員變量聲明成 final珍坊。
  • final 產(chǎn)生了某種程度的不可變 (immutable) 的效果阵漏,所以履怯,可以用來保護只讀數(shù)據(jù)叹洲,尤其是在并發(fā)編程中运提,因為明確地不能再賦值 final 變量民泵,有利于減少同步開銷栈妆,也可以省去一些防御性拷貝地必要鳞尔。

總結起來就是:聲明 final 關鍵字市框,從語義上告訴我們自己和閱讀枫振、合作一起編程的人,這是一個不可變對象乒疏,讓大家心中有底窍侧。同時 final 關鍵字的修飾硼啤,可以避免我們自己不小心的意外賦值谴返,也可以保護只讀數(shù)據(jù),減少防御性拷貝的必要渠抹,避免別人意外賦值。

對于finally,我認為明確知道怎么使用就夠了三椿,推薦使用 Java 7 中添加的 try-with-resources 語句伴郁,因為通常 Java 平臺能夠更好地處理異常情況剂陡,編碼量也要少很多鸭栖,何樂而不為呢。

另外可以注意下 finally 一些特殊的不會被執(zhí)行的情況。比如

  1. System.exit(1)
try {
  // do something
  System.exit(1);
} finally{
  System.out.println(“Print from finally”);
}
  1. 死循環(huán)
try {
  while (true) {
    System.out.println("hello world");
  }
} finally {
  System.out.println("hello world");
}
  1. 線程被殺死
    當執(zhí)行 try-finally 的線程被殺死時屑墨。finally 也無法執(zhí)行。

對于 finalize卵史,我們要明確它是不被推薦使用的灿里,在業(yè)界的實踐證明中,一再證明它不是個好的辦法程腹,在 Java 9 中匣吊,甚至將 Object.finalize() 標記為 deprecated!如果沒有特別的原因寸潦,不要實現(xiàn) finalize 方法色鸳,也不要指望利用它來進行資源回收。

簡單說见转,我們無法保證 finalize 什么時候執(zhí)行命雀,執(zhí)行是否符合預期。使用不當會影響性能斩箫,導致程序死鎖梧油、掛起等。

如果要實現(xiàn)資源回收甘晤,推薦使用 try-with-resources 或者 try-finally 機制撮弧。如果需要額外處理,可以考慮 Java 提供的 Cleaner 機制或者其他替代辦法易核。

知識擴展

  1. final 不是 immutable 匈织!

當 final 修飾對象時,實際上只能約束指向這個對象的引用不可以被重新賦值牡直,但是對象內部的行為不被 final 影響缀匕,典型的行為就是 final 修飾普通 List 時,普通 List 仍然可以添加碰逸、刪除對象乡小。另外,如果要使 List 實現(xiàn) immutable饵史,可以考慮 List.of() 方法满钟。

  1. 如何構建一個 Immutable 對象

Immutable 在很多場景是非常棒的選擇掸哑,某種意義上說,Java 語言目前并沒有原生的不可變支持零远,如果需要實現(xiàn) Immutable 的類苗分,我們需要做到:

  • 將 class 自身聲明為 final,這樣別人就不能通過擴展來繞過限制了牵辣。
  • 將所有成員變量定義為 private 和 final摔癣,并且不要實現(xiàn) setter 方法。
  • 通常構造對象時纬向,成員變量使用深度拷貝來初始化择浊,而不是直接賦值,這是一種防御措施逾条,因為你無法確定輸入對象不被其他人修改琢岩。
  • 如果確實需要實現(xiàn) gettter 方法,或者其他可能會返回內部對象的方法师脂,使用 copy-on-write 原則担孔,創(chuàng)建私有的 copy。
  1. finalize 真的那么不堪嗎吃警?

答案是肯定的糕篇。

  • finalize 會拖慢垃圾收集,對于消耗高頻的資源酌心,這是不可忍受的拌消。

finalize 被設計成在垃圾收集之前調用,一旦實現(xiàn)了非空的 finalize 方法安券,就會導致回收呈現(xiàn)數(shù)量級上的變慢墩崩,有人專門做過 benchmark,大概是 40~50 倍的下降侯勉。

實踐中鹦筹,因為 finalize 拖慢垃圾收集,導致大量對象堆積壳鹤,這也是一種典型的 OOM 的原因盛龄。

  • finalize 回掩蓋資源回收時出錯的信息饰迹,下面這段代碼節(jié)選自 JDK 中的 java.lang.ref.Finalizer
 private void runFinalizer(JavaLangAccess jla) {
 //  ... 省略部分代碼
 try {
    Object finalizee = this.get(); 
    if (finalizee != null && !(finalizee instanceof java.lang.Enum)) {
       jla.invokeFinalize(finalizee);
       // Clear stack slot containing this variable, to decrease
       // the chances of false retention with a conservative GC
       finalizee = null;
    }
  } catch (Throwable x) { }
    super.clear(); 
 }
  1. 替代 finalize 的方法芳誓。

Java 平臺目前正在逐步使用 java.lang.ref.Cleaner 來替換掉原有的 finalize 實現(xiàn)。 Cleaner 的實現(xiàn)利用了幻象引用(PhantomReference)啊鸭,這是一種常見的所謂 post-mortem 清理機制锹淌。

下面是一段 JDK 提供的 Cleaner 的樣例

public class CleaningExample implements AutoCloseable {
        // A cleaner, preferably one shared within a library
        private static final Cleaner cleaner = <cleaner>;
        static class State implements Runnable { 
            State(...) {
                // initialize State needed for cleaning action
            }
            public void run() {
                // cleanup action accessing State, executed at most once
            }
        }
        private final State;
        private final Cleaner.Cleanable cleanable
        public CleaningExample() {
            this.state = new State(...);
            this.cleanable = cleaner.register(this, state);
        }
        public void close() {
            cleanable.clean();
        }
    }

吸取了 finalize 的教訓,每個 Cleaner 的操作都是獨立的赠制,它有自己的運行線程赂摆,可以避免意外死鎖等問題挟憔。

但是從可預測的角度來判斷,Cleaner 或者幻象引用改善的程度仍然是有限的烟号,由于種種原因導致幻象引用堆積绊谭,同樣回出現(xiàn)問題。所以汪拥,Cleaner 適合作為一種最后的保證手段达传,而不是完全依賴 Cleaner 進行資源回收。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末迫筑,一起剝皮案震驚了整個濱河市宪赶,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌脯燃,老刑警劉巖搂妻,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異辕棚,居然都是意外死亡欲主,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進店門逝嚎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來岛蚤,“玉大人,你說我怎么就攤上這事懈糯〉佣剩” “怎么了?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵赚哗,是天一觀的道長她紫。 經(jīng)常有香客問我,道長屿储,這世上最難降的妖魔是什么贿讹? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮够掠,結果婚禮上民褂,老公的妹妹穿的比我還像新娘。我一直安慰自己疯潭,他們只是感情好赊堪,可當我...
    茶點故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著竖哩,像睡著了一般哭廉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上相叁,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天遵绰,我揣著相機與錄音辽幌,去河邊找鬼。 笑死椿访,一個胖子當著我的面吹牛乌企,可吹牛的內容都是我干的。 我是一名探鬼主播成玫,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼逛犹,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了梁剔?” 一聲冷哼從身側響起虽画,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎荣病,沒想到半個月后码撰,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡个盆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年脖岛,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片颊亮。...
    茶點故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡柴梆,死狀恐怖,靈堂內的尸體忽然破棺而出终惑,到底是詐尸還是另有隱情绍在,我是刑警寧澤,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布雹有,位于F島的核電站偿渡,受9級特大地震影響,放射性物質發(fā)生泄漏霸奕。R本人自食惡果不足惜溜宽,卻給世界環(huán)境...
    茶點故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望质帅。 院中可真熱鬧适揉,春花似錦、人聲如沸煤惩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽盟庞。三九已至吃沪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間什猖,已是汗流浹背票彪。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留不狮,地道東北人降铸。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像摇零,于是被迫代替她去往敵國和親推掸。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,619評論 2 354

推薦閱讀更多精彩內容

  • 1. Java基礎部分 基礎部分的順序:基本語法驻仅,類相關的語法谅畅,內部類的語法,繼承相關的語法噪服,異常的語法毡泻,線程的語...
    子非魚_t_閱讀 31,623評論 18 399
  • (一)Java部分 1、列舉出JAVA中6個比較常用的包【天威誠信面試題】 【參考答案】 java.lang;ja...
    獨云閱讀 7,101評論 0 62
  • 一粘优、Java 簡介 Java是由Sun Microsystems公司于1995年5月推出的Java面向對象程序設計...
    子非魚_t_閱讀 4,183評論 1 44
  • final仇味、finally和finalize的區(qū)別是什么? 轉自(侵刪):http://blog.csdn.net...
    shu2man閱讀 601評論 0 1
  • 什么是適配器模式 當你想使用一個類的時候雹顺,但是這個類的接口跟你又不一樣丹墨,不能拿來直接用,這個時候就需要一個適配器來...
    PeterHe888閱讀 270評論 0 0