final關鍵字:阻止繼承
在 Java 中,宣告類、變數和方法時,可使用關鍵字 final 來修飾。
final:
final 所修飾的資料具有“終態”的特徵,表示“最終的”意思。具體規定如下:
- final 修飾的類不能被繼承。
- final 修飾的方法不能被子類重寫。
- final 修飾的變數(成員變數或區域性變數)即成為常量,只能賦值一次。
- final 修飾的成員變數必須在宣告的同時賦值,如果在宣告的時候沒有賦值,那麼只有 一次賦值的機會,而且只能在構造方法中顯式賦值,然後才能使用。
- final 修飾的區域性變數可以只宣告不賦值,然後再進行一次性的賦值。
final用途:
1.用於修飾那些通用性的功能、實現方式或取值不能隨意被改變的資料,以避免被誤用。如數學常量
2.引用型別(任何類的型別)的變數標記為 final,那麼該變數不能指向任何其它物件。但可以改變物件的內容,因為只有引用本身是 final 的。
3.final 也可以用來修飾類(放在 class 關鍵字前面),阻止該類再派生出子類,例如 Java.lang.String 就是一個 final 類。這樣做是出於安全原因,因為要保證一旦有字串的引用,就必須是類 String 的字串,而不是某個其它類的字串(String 類可能被惡意繼承並篡改)。
4.方法也可以被 final 修飾,被 final 修飾的方法不能被覆蓋;變數也可以被 final 修飾,被 final 修飾的變數在建立物件以後就不允許改變它們的值了。一旦將一個類宣告為 final,那麼該類包含的方法也將被隱式地宣告為 final,但是變數不是。
5.被 final 修飾的方法為靜態繫結,不會產生多型(動態繫結),程式在執行時不需要再檢索方法表,能夠提高程式碼的執行效率。在Java中,被 static 或 private 修飾的方法會被隱式的宣告為 final,因為動態繫結沒有意義。
6.不允許子類處理這些問題。如Calendar類的設計者負責實現Date類與日曆狀態之間的轉換,而不允許子類處理這些問題。
由於動態繫結會消耗資源並且很多時候沒有必要,所以有一些程式設計師認為:除非有足夠的理由使用多型性,否則應該將所有的方法都用 final 修飾。
這樣的認識未免有些偏激,因為 JVM 中的即時編譯器能夠實時監控程式的執行資訊,可以準確的知道類之間的繼承關係。如果一個方法沒有被覆蓋並且很短,編譯器就能夠對它進行優化處理,這個過程為稱為內聯(inlining)。例如,內聯呼叫 e.getName() 將被替換為訪問 e.name 變數。這是一項很有意義的改進,這是由於CPU在處理呼叫方法的指令時,使用的分支轉移會擾亂預取指令的策略,所以,這被視為不受歡迎的。然而,如果 getName() 在另外一個類中被覆蓋,那麼編譯器就無法知道覆蓋的程式碼將會做什麼操作,因此也就不能對它進行內聯處理了。