final 在 Java 中是一個保留的關鍵字,能夠聲明變量、方法、類。編程
任何變量前被 final 修飾就是 final 變量,定義的類前被 final 修飾就是 final 類,任何方法前被 final 修飾就是final方法。緩存
當用 final 修飾一個類時,代表這個類不能被繼承。圖中箭頭指向的地方,那句英文翻譯過來就是不能繼承 Cat 類。安全
若是把 final 關鍵字去掉,就能夠了。這樣就不會報錯了!多線程
使用final類要注意,一旦被設置爲final類就沒法被繼承 app
下面這段話摘自《Java編程思想》第四版第143頁:性能
「使用 final 方法的緣由有兩個。第一個緣由是把方法鎖定,以防任何繼承類修改它的含義;第二個緣由是效率。在早期的Java實現版本中,會將final方法轉爲內嵌調用。可是若是方法過於龐大,可能看不到內嵌調用帶來的任何性能提高。在最近的 Java 版本中,不須要使用 final 方法進行這些優化了。「優化
意思是若是方法足夠完整,子類不須要修改就可使用final方法,避免子類被修改。final方法是靜態綁定的,在編譯時就肯定好是哪一個類的方法,因此final方法要比非final方法快一些spa
變量被 final 修飾就是就是 final 變量,那麼問題來了,final 變量和普通變量到底有啥區別?線程
舉個栗子:翻譯
public class Main { public static void main(String[] args) { String a = "xiaomeng2"; final String b = "xiaomeng"; String d = "xiaomeng"; String c = b + 2; String e = d + 2; System.out.println((a == c)); System.out.println((a == e)); } }
true
false
變量a指的是字符串常量池中的 xiaomeng2;
變量 b 是 final 修飾的,變量 b 的值在編譯時候就已經肯定了它的值,換句話說就是提早知道了變量 b 的內容究竟是個啥,至關於一個編譯期常量;
變量 c 是 b + 2獲得的,因爲 b 是一個常量,因此在使用 b 的時候直接至關於使用 b 的原始值(xiaomeng)來進行計算,因此 c 生成的也是一個常量,a 是常量,c 也是常量,都是 xiaomeng2 而 Java 中常量池中只生成惟一的一個 xiaomeng2 字符串,因此 a 和 c 是相等的!
d 是指向常量池中 xiaomeng,但因爲 d 不是 final 修飾,也就是說在使用 d 的時候不會提早知道 d 的值是什麼,因此在計算 e 的時候就不同了,e的話因爲使用的是 d 的引用計算,變量d的訪問卻須要在運行時經過連接來進行,因此這種計算會在堆上生成 xiaomeng2 ,因此最終 e 指向的是堆上的 xiaomeng2 , 因此 a 和 e 不相等。
也就是說a和c是常量池的xiaomeng2,e是堆上的xiaomeng2
final修飾的常量變量不可改變,修飾的引用變量引用不可改變,引用的對象可改變
舉個栗子:
修改普通變量int報錯
修飾的引用變量引用不可改變是什麼意思
再舉個栗子:
test是引用變量,被final修飾,若是再把test這個引用指向別的地方就會報錯
引用的對象可改變又是什麼意思
舉個栗子:
這段代碼執行結果是2,沒有報錯,說明test這個對象裏面i的值增長了1,引用對象的內容變了
final方法比非final快一些
final關鍵字提升了性能。JVM和Java應用都會緩存final變量。
final變量能夠安全的在多線程環境下進行共享,而不須要額外的同步開銷。
使用final關鍵字,JVM會對方法、變量及類進行優化。