當一個類有多個構造函數的時候,常使用this構造器:
public class SomeClass{public SomeClass(){//TODO:初始化一些字段}public SomeClass(string temp) : this(){//TODO:初始化另外一些字段}}
在這裡,為什麼要使用this構造器呢?這事還要從字段的初始化說起。
假設有這樣的一個類,在聲明字段的時候對字段進行了初始化。在客戶端,通過該類的2個構造函數創建對象實例。
class Program{static void Main(string[] args){SomeClass sc = new SomeClass();SomeClass sc1 = new SomeClass("jack");}}public class SomeClass{private int _age = 20;private string _name = "darren";public SomeClass(){}public SomeClass(string name){_name = name;}}
反編譯成IL代碼為:
可見,每次調用類的構造函數都會對_age和_name字段進行初始化。是否可以把這重復的部分放到一個公共的地方呢?答案是可以的,可以把字段的初始化工作交給一個無參構造函數。修改如下:
public class SomeClass{private int _age;private string _name;public SomeClass(){_age = 20;_name = "darren";}public SomeClass(string name) : this(){_name = name;}}
以上,在SomeClass的有參構造函數中,沒有對_age和_name字段再次進行初始化,而是調用了SomeClass的無參構造函數,可見,使用this構造器避免了重復初始化字段。
假如我們允許把this 和super放置到任何位置。那麼請看下面代碼:class A{ A() { System.out.println("You call super class non-args constructor!"); }} class B extends A{ B() { //這裡,編譯器將自動加上 super(); System.out.println("You call subclass constructor!"); } B(String n) { super(); this();//實際就是調用了B(){...},而在B(){...}中編譯器自動加上了 //super();這樣就相當於兩次調用了super();也就是說對父類進//行了兩次初始化。而在實例化一個對象時,一個構造方法只能調用一次,這說明this和super不能同時存在一個構造方法中。同時因為系統沒有在第一行發現this()或super()調用,就會自動加上super(),如果沒有將this()和super()放在第一行就會產生矛盾。 //因為總有一個super()在第二句上。所以該程序不能通過編譯!!! }也就是說你必須在構造器的第一行放置super或者this構造器,否則編譯器會自動地放一個空參數的super構造器的,其他的構造器也可以調用super或者this,調用成一個遞歸構造鏈,最後的結果是父類的構造器(可能有多級父類構造器)始終在子類的構造器之前執行,遞歸的調用父類構造器。無法執行當前的類的構造器。也就不能實例化任何對象,這個類就成為一個無為類。從另外一面說,子類是從父類繼承而來,繼承了父類的屬性和方法,如果在子類中先不完成父類的成員的初始化,則子類無法使用,應為在java中不允許調用沒初始化的成員。在構造器中是順序執行的,也就是說必須在第一行進行父類的初始化。而super能直接完成這個功能。This()通過調用本類中的其他構造器也能完成這個功能。
this() super()
是你如果想用傳入當前構造器中的參數或者構造器中的數據調用其他構造器或者控制父類構造器時使用的,在一個構造器中你只能使用this()或者super()之中的一個,而且調用的位置只能在構造器的第一行,在子類中如果你希望調用父類的構造器來初始化父類的部分,那就用合適的參數來調用super(),如果你用沒有參數的super()來調用父類的構造器(同時也沒有使用this()來調用其他構造器),父類缺省的構造器會被調用,如果父類沒有缺省的構造器,那編譯器就會報一個錯誤。
為什麼要在第一排呢?
example:
class A{
A() {
System.out.println("You call super class non-args constructor!");
}
}
class B extends A{
B() {
//這裡,編譯器將自動加上 super();
System.out.println("You call subclass constructor!");
}
B(int c){
System.out.println("wrong,wrong");
}
B(String n) {
這裡為空 // super();
System.out.println("想想就是這樣");
this();
//實際就是調用了B(){...},而B(){...}已經調用過一次,super();所以super()就被調用兩次,也就是對A進行了兩次初始化。而在實例化一個對象時,一 個 構造方法只能調用一次,這然顯然是不對的.
}
B(double c){
this();
this(3);
//這裡實際上也是調用兩次super(),也就是對A進行兩次初始化,所以其結果也不對
}
}
注:任意一個類,它都一定有父類,如果你沒有建立該類的父類,那麼該類的父類為Object;