1. 程式人生 > >Java核心-03 談談final、finally、 finalize有什麽不同?

Java核心-03 談談final、finally、 finalize有什麽不同?

推薦 垃圾 源碼 私有 pri jdk 收集 hotspot 減少

今天,我要問你的是一個經典的 Java 基礎題目,談談 final、finally、 finalize 有什麽不同?

典型回答

final 可以用來修飾類、方法、變量,分別有不同地意義,final修飾地 class 代表不可以繼承擴展,final 的變量是不可以修改的,而 final 的方法也是不可以重寫的(override)。

finally 則是 java保證重點代碼一定要被執行的一種機制。我們可以使用 try-finally 或者 try-catch-finally 來進行類似關閉 JDBC 連接、保證 unlock 鎖等動作。

finalize 是基礎類 java.lang.Object 的一個方法,它的設計目的是保證對象在被垃圾收集前完成特定資源的回收

。finalize 機制現在已經不推薦使用,並且在 JDK 9 開始被標記為 deprecated。

這是一個非常經典的 java 基礎問題,我上面的回答主要是從語法和是使用實踐角度出發的。面試官還可以考察你對性能、並發、對象生命周期或垃圾收集基本過程等方面的理解。

推薦使用 final 關鍵字來明確表示我們代碼的語義、邏輯意圖,這已經被證明在很多場景下是非
常好的實踐,比如:

  • 我們可以將方法或類聲明為final,這樣就可以明確告知別人,這些行為是不許修改的。

如果你關註過 Java 核心類庫的定義或源碼,有沒有發現 Java.lang 包下面很多類,相當一部分被聲明為 final class?在第三方類庫的一些基礎類中同樣如此,這樣可以有效避免 API 使用者更改基礎功能,某種程度上,這是保證平臺安全的必要手段。

  • 使用 final 修飾參數或者變量,也可以清楚地避免意外賦值導致的編程錯誤,甚至,有人明確推薦將所有方法參數、本地變量、成員變量聲明成 final。
  • final 變量產生了某種程度的不可變(immutable)的效果,所以,可以用於保護只讀數據,尤其是在並發編程中,因為明確地不能再賦值 final 變量,有利於減少額外的同步開銷,也可
    以省去一些防禦性拷貝的必要。
  • final 也許會有性能的好處,很多文章或者書籍中都介紹了可在特定場景提高性能,比如,利用final 可能有助於 JVM 將方法進行內聯,可以改善編譯器進行條件編譯的能力等等。坦白說,很多類似的結論都是基於假設得出的,比如現代高性能 JVM(如 HotSpot)判斷內聯未必依賴final 的提示,要相信 JVM 還是非常智能的。類似的,final 字段對性能的影響,大部分情況下,並沒有考慮的必要 。

知識擴展
1. 註意,final 不是 immutable!
我在前面介紹了 final 在實踐中的益處,需要註意的是,final 並不等同於 immutable,比如下
面這段代碼

final List<String> strList = new ArrayList<>();
strList.add("Hello");
strList.add("world");
List<String> unmodifiableStrList = List.of("hello", "world");
unmodifiableStrList.add("again");

final 只能約束 strList 這個引用不可以被賦值,但是 strList 對象行為不被 final 影響,添加元素
等操作是完全正常的。如果我們真的希望對象本身是不可變的,那麽需要相應的類支持不可變的
行為。在上面這個例子中,List.of 方法創建的本身就是不可變 List,最後那句 add 是會在運行
時拋出異常的。

Immutable 在很多場景是非常棒的選擇,某種意義上說,Java 語言目前並沒有原生的不可變支
持,如果要實現 immutable 的類,我們需要做到:

  • 將 class 自身聲明為 final,這樣別人就不能擴展來繞過限制了。
  • 將所有成員變量定義為 private 和 final,並且不要實現 setter 方法。
  • 通常構造對象時,成員變量使用深度拷貝來初始化,而不是直接賦值,這是一種防禦措施,
    因為你無法確定輸入對象不被其他人修改。
  • 如果確實需要實現 getter 方法,或者其他可能會返回內部狀態的方法,使用 copy-on-write
    原則,創建私有的 copy。

關於 setter/getter 方法,很多人喜歡直接用 IDE 一次全部生成,建議最好是你確定有需要時再
實現。

Java核心-03 談談final、finally、 finalize有什麽不同?