一、Composition 語法
(1)Object references 會被初始化爲 null;
(2)爲減少不必要的負擔,compiler 不會爲每個 reference 産生 default object;
(3)初始化 object references:
- 在對象定義處:表示它們一定能在 constructor 被調用前完成 initialization;
- 在 constructor 內;
- 在實際需要使用到該對象的地方:這種方法稱爲 lazy initialization,可減少額外的負擔。
二、Inheritance 語法
(1)Inheritance 是 Java 不可或缺的一個部分,即使沒有指出要繼承某個 class,仍會隱式的繼承 Java 的標准根源類 Object;
(2)爲每個 class 都撰寫 main() 以方便進行 unit testing(Bruce 說的,本人…保留意見);
(3)Inheritance 的一般性原則:data members 聲明爲 private,methods 聲明爲 public;
(4)Java 通過 keyword super 來調用 base-class;
(5)對 base-class 的 constructor 的調用,是 derived-class 的 constructor 所做的第一件事(Compiler 強制)。即使沒有爲 derived-class 撰寫 constructor,compiler 也會爲其自動合成;
(6)基於(5),若 base-class 的 constructor 帶有 arguments,derived-class 的 constructor 必須首先在起始處使用 super(arguments) 對 base-class 進行 initialization;
(7)與生成的順序相反,cleanup 的次序是先 derived-class 後 base-class;
(8)Name hiding:derived-class 內重新定義(使用)了 base-class 的 method 名稱,除非 method 的名稱以及 arguments 都完全相同(即 Override),否則並不會屏蔽它在 base-class 的版本。
三、Composition 與 Inheritance 的選擇
(1)需要在新 class 中使用既有 class 的功能而非其接口,通常使用 composition,新 class 中以 private 形式嵌入既有 class 的對象(即 has - a 關系);
(2)需要使用某個通用性的 class,並基於特定目的對其進行 specializing 工程時,使用 inheritance(即 is - a 關系)。
四、Upcasting
(1)Upcasting:將 derived-class reference 轉爲 base-class reference 的動作。Upcasting 之所以可以進行是因爲 derived-class 其實也是 base-class 對象(即 is - a 關系);
(2)Derived-class 是 base-class 的一個超集合,它至少包含 base-class 的 method,而且可能更多,所以 upcasting 過程中對 class 接口造成的唯一效應是 method 的“丟失”而非“獲得”,這也是 compiler 允許 upcasting 的原因。
五、The final keyword
(1)Final 的適用範圍:data、method、class。
(2)Final data
- 固定不變的 data:
- 1. 永不改變的 compile-time constant:意味著在 compile-time 就可以執行某些計算,從而減少 run-time 的負擔,所以此類 constant 必須是基本類型,而且在定義時就必須給定其值;
- 2. 可以在 run-time 被初始化,不可再改變。
- 如果 data 既是 final 也是 static,那麽它就擁有一塊無法改變的存儲空間;
- final 修飾的 object reference 被初始化以後就不能改而指向其它 object,但 object 本身的內容卻是可以改變的;
- 沒有方法可以使 array reference 本身成爲 final。
(3)Blank finals:Java 允許産生 blank final,也就是將 data members 聲明爲 final 但不給予初值。但在任何情況下,blank finals 都必須在使用前完成 initialization(Compiler 強制);
(4)Final arguments:Java 允許將 arguments 聲明爲 final,這意味著 arguments 在 method 內是只讀的;
(5)Final methods
-
- 使用 final methods 的原因:
- 鎖住 method,使其在 derived-class 內爲只讀,無法被 override;
- 出於效率考量:允許 compiler 將此 method 的調用動作轉爲 inline 調用(即不通過 stack,直接調用 method 本體從而提高效率)而非正常的處理方式,所以除非函數足夠小,否則 inlining 可能會適得其反,使效率降低。
- final & private
- private 也是 final:因爲無法取用 private,自然也就無從 override(但對 private method 進行 override 並不會出錯,因爲 override 實際上並沒有成功,只是産生了一個新的 method),final 可加於 private method 上,但不會帶來任何額外的意義;
- Overriding 只能發生在 method 屬於 base-class 接口時,也就是說,你必須可以將某對象 upcasting 至其 base-class,並調用同一個(同名)method,overriding 才可以使用。
- final class 不能被繼承、改動;
- 無論 class 是否爲 final,data members 都可以是或不是 final,final data 的原始規則仍然適用;
- final class 是要阻止 inheritance,所以 final class 中的所有 method 自然也是 final,因爲它們不能 override(所以 final class 內的 method 加不加 final 都可以)。
- Loading:derived-class -> base-class -> … -> root base-class
- Initialization: root base-class -> base-class -> … -> leaf derived-class
- Basic type -> default value
- Object reference -> null
- 喚起 base-class constructor(也可以使用 super 進行調用)。
- 完成 base-class 的 constructor;
- instance 變量按序被 initialize;
- 執行 constructor 本體的剩餘部分。
(6)Final classes
六、Initialization & Class loading
(1)有別於傳統語言,Java 的 class 程序代碼在初次被調用時才裝載(初次被調用不僅是指第一個對象被構建之時,也可能是 static member/method 被訪問時;
(2)首次使用 class 的時間點也正是 static initialization 發生的時候(static object/code block 被裝載時按序進行 initialization)。
七、Initialization with Inheritance
(1)Loading & Intialization 的順序:
(2)産生對象:
(3)Base-class construction:
