super使用在構(gòu)造方法中,語法格式為:super(實際參數(shù)列表),這行代碼和“this(實際參數(shù)列表)”都是只允許出現(xiàn)在構(gòu)造方法第一行(這一點記住就行了),所以這兩行代碼是無法共存的。“super(實際參數(shù)列表)”這種語法表示子類構(gòu)造方法執(zhí)行過程中調(diào)用父類的構(gòu)造方法。我們來看一段代碼:
public class People {
String idCard;
String name;
boolean sex;
public People(){
}
public People(String idCard,String name,boolean sex){
this.idCard = idCard;
this.name = name;
this.sex = sex;
}
}
public class Student extends People{
//學(xué)號是子類特有的
int sno;
public Student(){
}
public Student(String idCard,String name,boolean sex,int sno){
this.idCard = idCard;
this.name = name;
this.sex = sex;
this.sno = sno;
}
}
public class StudentTest {
public static void main(String[] args) {
Student s = new Student("12345x","jack",true,100);
System.out.println("身份證號" + s.idCard);
System.out.println("姓名" + s.name);
System.out.println("性別" + s.sex);
System.out.println("學(xué)號" + s.sno);
}
}
圖14-4:運行結(jié)果
我們把上面的代碼片段拿過來放在一起看看:
父類的構(gòu)造方法:
public People(String idCard,String name,boolean sex){
this.idCard = idCard;
this.name = name;
this.sex = sex;
}
子類的構(gòu)造方法:
public Student(String idCard,String name,boolean sex,int sno){
this.idCard = idCard;
this.name = name;
this.sex = sex;
this.sno = sno;
你有沒有察覺到子類的構(gòu)造方法前三行代碼和父類構(gòu)造方法中的代碼是一樣的?接下來把子類的構(gòu)造方法修改一下,然后再運行測試程序:
public Student(String idCard,String name,boolean sex,int sno){
super(idCard,name,sex);
this.sno = sno;
}
圖14-5:運行結(jié)果
通過以上代碼的學(xué)習(xí),“super(實際參數(shù)列表);”語法表示調(diào)用父類的構(gòu)造方法,代碼復(fù)用性增強(qiáng)了,另外一方面也是模擬現(xiàn)實世界當(dāng)中的“要想有兒子,必須先有父親”的道理。不過這里的“super(實際參數(shù)列表)”在調(diào)用父類構(gòu)造方法的時候,從本質(zhì)上來說并不是創(chuàng)建一個“獨立的父類對象”,而是為了完成當(dāng)前對象的父類型特征的初始化操作。(或者說通過子類的構(gòu)造方法調(diào)用父類的構(gòu)造方法,是為了讓張小明身上長出具有他父親特點的鼻子和眼睛,鼻子和眼睛初始化完畢之后,具有父親的特點,但最終還是長在張小明的身上)。
接下來,再來看一段代碼:
public class A {
public A(){
System.out.println("A類的無參數(shù)構(gòu)造方法執(zhí)行");
}
}
public class B extends A {
public B(){
System.out.println("B類的無參數(shù)構(gòu)造方法執(zhí)行");
}
}
public class C extends B {
public C(){
System.out.println("C類的無參數(shù)構(gòu)造方法執(zhí)行");
}
}
public class Test {
public static void main(String[] args) {
new C();
}
}
圖14-6:super()的測試
通過以上運行結(jié)果可以得出以下的等效代碼:
public class A {
public A(){
//這里調(diào)用的是Object類中的無參數(shù)構(gòu)造方法
//因為A類的父類是Object
super();
System.out.println("A類的無參數(shù)構(gòu)造方法執(zhí)行");
}
}
public class B extends A {
public B(){
super();
System.out.println("B類的無參數(shù)構(gòu)造方法執(zhí)行");
}
}
public class C extends B {
public C(){
super();
System.out.println("C類的無參數(shù)構(gòu)造方法執(zhí)行");
}
}
圖14-7:super()的測試
通過以上代碼的測試我們得出,當(dāng)一個構(gòu)造方法第一行沒有顯示的調(diào)用“super(實際參數(shù)列表)”的話,系統(tǒng)默認(rèn)調(diào)用父類的無參數(shù)構(gòu)造方法“super()”。當(dāng)然前提是“this(實際參數(shù)列表)”也沒有顯示的去調(diào)用(因為super()和this()都只能出現(xiàn)在構(gòu)造方法第一行,所以不能并存)。我們可以通過以下程序再次測試一下:
public class A {
//有參數(shù)構(gòu)造方法定義之后
//系統(tǒng)則不再提供無參數(shù)構(gòu)造方法
public A(String s){
}
}
public class B extends A {
public B(){
}
}
圖14-8:編譯報錯信息
以上程序為什么會編譯報錯呢?原因是B類的構(gòu)造方法第一行默認(rèn)會調(diào)用“super()”,而super()會調(diào)用父類A的無參數(shù)構(gòu)造方法,但由于父類A中提供了有參數(shù)構(gòu)造方法,導(dǎo)致無參數(shù)構(gòu)造方法不存在,從而編譯報錯了。所以在實際開發(fā)中還是建議程序員將無參數(shù)構(gòu)造方法顯示的定義出來,這樣就可以避免對象的創(chuàng)建失敗了。
另外,通過以上內(nèi)容的學(xué)習(xí),還可以得出這樣的結(jié)論:在java語言當(dāng)中無論是創(chuàng)建哪個java對象,老祖宗Object類中的無參數(shù)構(gòu)造方法是必然執(zhí)行的。
接下來我們再來看一下:一個java對象在創(chuàng)建過程中比較完整的內(nèi)存圖是如何變化的,請先看以下代碼:
public class People {
String name;
boolean sex;
public People(String name,boolean sex){
this.name = name;
this.sex = sex;
}
}
public class Worker extends People {
//子類特有的工資屬性
double salary;
public Worker(String name,boolean sex,double salary){
super(name,sex);
this.salary = salary;
}
}
public class WorkerTest {
public static void main(String[] args) {
Worker w = new Worker("jack",true,10000.0);
System.out.println("姓名:" + w.name);
System.out.println("性別:" + w.sex);
System.out.println("工資:" + w.salary);
}
}
圖14-9:運行結(jié)果
以上程序創(chuàng)建Worker對象時構(gòu)造方法的執(zhí)行順序是:
● 先執(zhí)行Object類的無參數(shù)構(gòu)造方法;
● 再執(zhí)行People類的構(gòu)造方法;
● 最后執(zhí)行Worker類的構(gòu)造方法;
注意:雖然執(zhí)行了三個構(gòu)造方法,但是對象實際上只創(chuàng)建了一個Worker。
以上程序的內(nèi)存結(jié)構(gòu)圖是這樣變化的:
圖14-10:程序執(zhí)行內(nèi)存圖
通過以上內(nèi)容的學(xué)習(xí),super()的作用主要是:第一,調(diào)用父類的構(gòu)造方法,使用這個構(gòu)造方法來給當(dāng)前子類對象初始化父類型特征;第二,代碼復(fù)用。