【學習筆記】 唐大仕—Java程式設計 第5講 深入理解Java語言之5.3 物件構造與初始化
阿新 • • 發佈:2018-11-10
物件構造與初始化
構造方法
-
構造方法(constructor)
- 物件都有構造方法
- 如果沒有,編譯器加一個default構造方法
-
抽象類(abstract)有沒有構造方法?
- 答案:抽象類也有構造方法。實際上,任何類都有自己的構造方法
呼叫本類或父類的構造方法
-
呼叫本類或父類的構造方法
- this呼叫本類的其他構造方法
- super呼叫父類的構造方法
- this和super要放在第一條語句,且只能夠有一條
-
如果沒有this及super,則編譯器自動加上super()
-
因為必須令所有父類的構造方法都得到呼叫,否則整個物件的構建就可能不正確
建立物件時初始化
- p = new Person(){{ age = 18; name = "李明" }}
- 這樣可以針對沒有相應建構函式,但又要賦值的情況
- 注意雙括號
例項初始化與靜態初始化
-
例項初始化(Instance Initializers)
-
在類中直接寫
- { 語句.... }
- 例項初始化,先於構造方法{}中的語句執行
-
靜態初始化(Static Initializers)
- static{ 語句.... }
- 靜態初始化,在第一次使用這個類時要執行
- 但其執行的具體時機是不確定的
- 但是可以肯定的是:總是先於例項的初始化
構造方法的執行過程
-
構造方法的執行過程遵照以下步驟:
- 呼叫本類或父類的構造方法,直至最高一層(Object)
- 按照宣告順序執行欄位的初始化賦值
- 執行建構函式中的各語句
-
簡單的說:
- 先父類構造,再本類成員賦值,最後執行構造方法中的語句
一個問題
- 構造方法內部呼叫別的方法
- 如果這個方法是虛方法(不是用private,private,final修飾的方法),結果如何?
- 從語法上來說這是合法的,但有時會造成事實上的不合理
class ConstructInvokeMetamorph { public static void main(String[] args){ Person p = new Student("李明", 18, "北大"); } } class Person { String name="未命名"; int age=-1; Person( String name, int age ){ this.name=name; this.age=age; sayHello(); } void sayHello(){ System.out.println( "我是一個人,我名叫:" + name + ",年齡為:"+ age ); } } class Student extends Person { String school="未定學校"; Student( String name, int age, String school ){ super( name, age ); this.school = school; } void sayHello(){ System.out.println( "我是學生,我名叫:" + name + ",年齡為:"+ age + ",學校在:" + school ); } }
- 在本例中,在建構函式中呼叫了一個動態繫結的方法sayHello(),這時,會使用哪個方法被覆蓋的定義,而這時物件還沒有完全構建好,所以,School還沒有賦值
- 因此,可能的話,在構建器中避免呼叫任何方法,用盡可能簡單的方法使物件進入就緒狀態
- 唯一能夠安全呼叫的是具有final屬性的方法