標籤:
在 Java 中,聲明類、變數和方法時,可使用關鍵字 final 來修飾。final 所修飾的資料具有“終態”的特徵,表示“最終的”意思。具體規定如下:
- final 修飾的類不能被繼承。
- final 修飾的方法不能被子類重寫。
- final 修飾的變數(成員變數或局部變數)即成為常量,只能賦值一次。
- final 修飾的成員變數必須在聲明的同時賦值,如果在聲明的時候沒有賦值,那麼只有 一次賦值的機會,而且只能在構造方法中顯式賦值,然後才能使用。
- final 修飾的局部變數可以只聲明不賦值,然後再進行一次性的賦值。
final 一般用於修飾那些通用性的功能、實現方式或取值不能隨意被改變的資料,以避免被誤用,例如實現數學三角方法、冪運算等功能的方法,以及數學常量π=3.141593、e=2.71828 等。
事實上,為確保終態性,提供了上述方法和常量的 java.lang.Math 類也已被定義為final 的。
需要注意的是,如果將參考型別(任何類的類型)的變數標記為 final,那麼該變數不能指向任何其它對象。但可以改變對象的內容,因為只有引用本身是 final 的。
如果變數被標記為 final,其結果是使它成為常數。想改變 final 變數的值會導致一個編譯錯誤。下面是一個正確定義 final 變數的例子:
1 public final int MAX_ARRAY_SIZE = 25; // 常量名一般大寫
常量因為有 final 修飾,所以不能被繼承。
請看下面的代碼:
1 public final class Demo{ 2 public static final int TOTAL_NUMBER = 5; 3 public int id; 4 public Demo() { 5 // 非法,對final變數TOTAL_NUMBER進行二次賦值了 6 // 因為++TOTAL_NUMBER相當於 TOTAL_NUMBER=TOTAL_NUMBER+1 7 id = ++TOTAL_NUMBER; 8 } 9 public static void main(String[] args) {10 final Demo t = new Demo();11 final int i = 10;12 final int j;13 j = 20;14 j = 30; // 非法,對final變數進行二次賦值15 }16 }
final 也可以用來修飾類(放在 class 關鍵字前面),阻止該類再派生出子類,例如 Java.lang.String 就是一個 final 類。這樣做是出於安全原因,因為要保證一旦有字串的引用,就必須是類 String 的字串,而不是某個其它類的字串(String 類可能被惡意繼承並篡改)。
方法也可以被 final 修飾,被 final 修飾的方法不能被覆蓋;變數也可以被 final 修飾,被 final 修飾的變數在建立對象以後就不允許改變它們的值了。一旦將一個類聲明為 final,那麼該類包含的方法也將被隱式地聲明為 final,但是變數不是。
被 final 修飾的方法為靜態繫結,不會產生多態(動態綁定),程式在運行時不需要再檢索方法表,能夠提高代碼的執行效率。在Java中,被 static 或 private 修飾的方法會被隱式的聲明為 final,因為動態綁定沒有意義。
由於動態綁定會消耗資源並且很多時候沒有必要,所以有一些程式員認為:除非有足夠的理由使用多態性,否則應該將所有的方法都用 final 修飾。
這樣的認識未免有些偏激,因為 JVM 中的即時編譯器能夠即時監控程式的運行資訊,可以準確的知道類之間的繼承關係。如果一個方法沒有被覆蓋並且很短,編譯器就能夠對它進行最佳化處理,這個過程為稱為內聯(inlining)。例如,內聯調用 e.getName() 將被替換為訪問 e.name 變數。這是一項很有意義的改進,這是由於CPU在處理調用方法的指令時,使用的分支轉移會擾亂預取指令的策略,所以,這被視為不受歡迎的。然而,如果 getName() 在另外一個類中被覆蓋,那麼編譯器就無法知道覆蓋的代碼將會做什麼操作,因此也就不能對它進行內聯處理了。
系列文章:
Java知多少(1)語言概述
Java知多少(2)虛擬機器(JVM)以及跨平台原理
Java知多少(3) 就業方向
Java知多少(4)J2SE、J2EE、J2ME的區別
Java知多少(5) Java開發環境的搭建
Java知多少(6)第一個程式樣本
Java知多少(7)類與對象
Java知多少(8)類庫及其組織圖
Java知多少(9) import及Java類的搜尋路徑
Java知多少(10)資料類型及變數
Java知多少(11)資料類型轉換
Java知多少(12)運算子
Java知多少(13)流程式控制制
Java知多少(14)數組
Java知多少(15)字串
Java知多少(16)StringBuffer與StringBuider
Java知多少(17)強調一下編程風格
Java知多少(18)類的定義及其執行個體化
Java知多少(19)存取修飾詞(存取控制符)
Java知多少(20)變數的範圍
Java知多少(21)this關鍵字詳解
Java知多少(22)方法重載
Java知多少(23)類的基本運行順序
Java知多少(24)封裝類、拆箱和裝箱詳解
Java知多少(25)再談Java包
Java知多少(26)源檔案的聲明規則
Java知多少(27)繼承的概念與實現
Java知多少(28)super關鍵字
Java知多少(29)覆蓋和重載
Java知多少(30)多態和動態綁定
Java知多少(31)static關鍵字以及Java靜態變數和靜態方法
Java知多少(32)instanceof
Java知多少(33)多態對象的類型轉換
Java知多少(34)final關鍵字:阻止繼承和多態
Java知多少(34)final關鍵字:阻止繼承和多態