代碼複用是面向對象編程最具魅力的原因之一。
對於像 C 語言等面向過程語言來說,“複用”通常指的就是“複製代碼”。
複用的兩種方式
-
在新類中創建現有類的對象。這種方式叫做“組合”,通過這種方式複用代碼的功能,而非其形式。
-
創建現有類型的新類。這種方式叫做“繼承”,編譯器會做大部分的工作。
初始化引用的四種方法
-
當對象被定義時。意味着它們總是在調用構造函數之前初始化。
-
在該類的構造函數中。
-
在實際使用對象之前。稱爲延遲初始化。在對象創建開銷大且不需要每次都創建對象的情況下,它可以減少開銷。
-
使用實例初始化。
再討論組合和繼承
一種判斷使用組合還是繼承的最清晰的方法是問一問自己是否需要把新類向上轉型爲基類。
如果必須向上轉型,那麼繼承就是必要的。
final 關鍵字
不能因爲某數據被 final 修飾就認爲在編譯時就可以知道它的值。
final 方法
過去建議使用 final 方法的原因是效率。在早期的 Java 實現中,如果將一個方法指明爲 final ,就是同意編譯器把對該方法的調用轉化爲內嵌調用。當編譯器遇到 final 方法的調用時,就會很小心地跳過普通的插入代碼以執行方法的調用機制(將參數壓棧,跳至方法代碼處執行,然後跳回並清理棧中的參數,最終處理返回值),而用方法體內實際代碼的副本替代方法調用。這種消除了方法調用的開銷,但是如果一個方法很大代碼膨脹,也許就看不到內嵌帶來的性能提升,因爲內嵌調用帶來的性能提升被花費在方法裏的時間抵消了。
在最近的 Java 版本中,虛擬機可以探測到這些情況(尤其是 hotspot 技術),並優化去掉這些效率反而降低的內嵌調用方法。有很長一段時間,使用 final 來提高效率都被阻止。應該讓編譯器和 JVM 處理性能問題,只有在爲了明確禁止覆寫方法時才使用 final。