深入java final關鍵字 基本用法、注意點和優點
本文講解final的基本用法和裡面的優缺點,原創不易,轉載請註明出處
文章分為3部分,分別會給大家介紹final關鍵字對類,方法和變數的修飾所起到的作用,以及一些優點,對於缺點大家可以參考《JAVA程式設計思想》第四版 156頁。
- final類及其優點
- final方法 及裡面要注意的一些小點
- final資料和final自變數 及我們需要注意的一些點(下一篇文章再說)
一:final類及其優點
如果我們用final關鍵字修飾java類的時候,那這個類就成為了final類。
為什麼使用final類:
1.這個類已經是一個十分完善的類,我們不會對其進行任何的改變,不希望這個類被任何人繼承改變它。
2.出於安全考慮,我們不希望進行子類化處理。
3.我們希望jvm在處理的時候,不再關心類是否被繼承,jvm不需要更多額外的處理,提高執行效率。
4.將類定義成 final後,結果只是禁止進行繼承——沒有更多的限制。然而,由於它禁止了繼承,所以一個 final類中的所有方法都預設為 final。final方法在編譯階段繫結,稱為靜態繫結(static binding),編譯時常量,永遠不可改變。jvm在執行的時候,會直接將final方法直接嵌進來,效率會大大提升。
常見的final類:
String Integer Double Boolean等等常見的包裝類都是不可變類。
final類的物件:
二:final方法 及裡面要注意的一些小點
方法前面加上final關鍵字,代表這個方法不可以被子類的方法重寫,這個方法就成為了final方法。一個方法的功能已經足夠完整了,子類中不需要改變的話,你可以宣告此方法為final。
為什麼使用final方法:
1.一個方法的功能已經足夠完整了,子類中不需要改變的話,就宣告此方法為final。
2.final方法比非final方法要快,因為在編譯的時候已經靜態綁定了,不需要在執行時再動態繫結。
3.要使用final 方法,可能是出於對兩方面理由的考慮:
第一:為方法“上鎖”,防止任何繼承類改變它的本來含義。設計程式時,若希望一個方法的行為在繼承期間保持不變,而且不可被覆蓋或改寫,就可以採取這種做法。
第二:程式執行的效率。將一個方法設成 final 後,編譯器就可以把對那個方法的所有呼叫都置入“嵌入”呼叫裡。只要編譯器發現一個final 方法呼叫,就會(根據它自己的判斷)忽略為執行方法呼叫機制而採取的常規程式碼插入方法(將自變數壓入堆疊;跳至方法程式碼並執行它;跳回來;清除堆疊自變數;最後對返回值進行處理)。相反,它會用方法主體內實際程式碼的一個副本來替換方法呼叫。這樣做可避免方法呼叫時的系統開銷。
我們需要注意到:若方法體積太大,那麼程式也會變得雍腫,可能受到到不到嵌入程式碼所帶來的任何效能提升。因為任何提升都被花在方法內部的時間抵消了。Java 編譯器能自動偵測這些情況,並頗為“明智”地決定是否嵌入一個final 方法。然而,最好還是不要完全相信編譯器能正確地作出所有判斷。通常,只有在方法的程式碼量非常少,或者想明確禁止方法被覆蓋的時候,才應考慮將一個方法設為final。
三:final資料和final自變數 及我們需要注意的一些點(下一篇文章再說)
final成員變數和自變數是指我們在成員變數和自變數前加final關鍵字修飾。
注意點:
1.final成員變數必須在宣告的時候初始化(static程式碼塊和普通程式碼塊)或者在構造器(建構函式)中初始化,否則就會報編譯錯誤。
2.不能夠對final變數再次賦值。
3.在匿名類中所有變數都必須是final變數。
4.(沒有在宣告時初始化final變數的稱為空白final變數(blank final variable),它們必須在構造器中初始化,或者呼叫this()初始化。不這麼做的話,編譯器會報錯“final變數(變數名)需要進行初始化”。)
5.JVM和Java應用都會快取final變數,以提高效能。
6.final變數可以安全的在多執行緒環境下進行共享,而不需要額外的同步開銷。