《Java 核心技术卷1 第10版》学习笔记------ 组织继承:final类和方法【编译器优化:内联( inlining );】
使用 final 關鍵字阻止繼承
有時候,可能希望阻止人們利用某個類定義子類。不允許擴展的類被稱為 final 類。如果在定義類的時候使用了 final 修飾符就表明這個類是 final 類。 例如, 假設希望阻止人們定義Executive類的子類,就可以在定義這個類的時候,使用 final 修飾符聲明。聲明格式如下所示:
public final class Executive extends Manager{... }
類中的特定方法也可以被聲明為 final。 如果這樣做,子類就不能覆蓋這個方法( final 類中的所有方法自動地成為 final 方法。) 例如:
注釋:前面曾經說過,域也可以被聲明為 final。對于 final 域來說,構造對象之后就不允許改變它們的值了。 不過, 如果將一個類聲明為 final, 只有其中的方法自動地成為 final,而不包括域。
將方法或類聲明為 final 主要目的是: 確保它們不會在子類中改變語義。例如, Calendar類中的 getTime 和 setTime 方法都聲明為 final。這表明 Calendar 類的設計者負責實現 Date 類與日歷狀態之間的轉換, 而不允許子類處理這些問題。同樣地, String 類也是 final 類,這意味著不允許任何人定義 String 的子類。換言之, 如果有一個 String 的引用, 它引用的一定是一個 String 對象, 而不可能是其他類的對象。
有些程序員認為: 除非有足夠的理由使用多態性, 應該將所有的方法都聲明為 final。事實上,在 C++ 和 C# 中, 如果沒有特別地說明, 所有的方法都不具有多態性。這兩種做法可能都有些偏激。我們提倡在設計類層次時, 仔細地思考應該將哪些方法和類聲明為 final。
在早期的 Java 中,有些程序員為了避免動態綁定帶來的系統開銷而使用 final 關鍵字。如果一個方法沒有被覆蓋并且很短, 編譯器就能夠對它進行優化處理, 這個過程為稱為內聯( inlining )。例如,內聯調用 e.getName( ) 將被替換為訪問 e.name 域。這是一項很有意義的改進, 這是由于 CPU 在處理調用方法的指令時, 使用的分支轉移會擾亂預取指令的策略, 所以,這被視為不受歡迎的。然而, 如果 getName 在另外一個類中被覆蓋, 那么編譯器就無法知道覆蓋的代碼將會做什么操作, 因此也就不能對它進行內聯處理了。
幸運的是, 虛擬機中的即時編譯器比傳統編譯器的處理能力強得多。這種編譯器可以準確地知道類之間的繼承關系, 并能夠檢測出類中是否真正地存在覆蓋給定的方法。 如果方法很簡短、 被頻繁調用且沒有真正地被覆蓋, 那么即時編譯器就會將這個方法進行內聯處理。如果虛擬機加載了另外一個子類,而在這個子類中包含了對內聯方法的覆蓋, 那么將會發生什么情況呢? 優化器將取消對覆蓋方法的內聯。這個過程很慢, 但卻很少發生。
?
總結
以上是生活随笔為你收集整理的《Java 核心技术卷1 第10版》学习笔记------ 组织继承:final类和方法【编译器优化:内联( inlining );】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《Java 核心技术卷1 第10版》学习
- 下一篇: 《Java 核心技术卷1 第10版》学习