當(dāng)創(chuàng)建了一個導(dǎo)出類的對象時,該對象包含了一個基類的子對象凶朗。這個子對象與你用基類直接創(chuàng)建的對象是一樣的苹祟。二者的區(qū)別在于,后者來自外部刑桑,而基類的子對象被包裝在導(dǎo)出類對象內(nèi)部。
當(dāng)然漓概,對基類子對象的正確初始化也是至關(guān)重要的漾月,而且也僅有一種方法來保證這一點:在構(gòu)造器中調(diào)用基類構(gòu)造器來執(zhí)行初始化,而基類構(gòu)造器中具有執(zhí)行基類初始化所需要的所有知識和能力胃珍。Java自動在導(dǎo)出類的構(gòu)造器中插入對基類構(gòu)造器的調(diào)用梁肿。
因為子類構(gòu)造器在執(zhí)行的時候會依次遞歸把其父類的構(gòu)造器都執(zhí)行一遍,所以我們可以在子類中獲取父類的方法觅彰、屬性吩蔑。有時候我們使用super
,這個super
指代的就是父類的對象填抬。
當(dāng)然也有不能自動執(zhí)行父類構(gòu)造器的時候:
class A {
A(int a) {
}
}
class B extends A{
}
如上述代碼所示烛芬,A類有一個含參數(shù)的構(gòu)造器,這個構(gòu)造器會替代原有的默認(rèn)構(gòu)造器飒责。所以B類就不能夠使用默認(rèn)構(gòu)造器了赘娄,必須手動調(diào)用A的參數(shù)構(gòu)造器。因為B類要調(diào)用A的構(gòu)造器宏蛉,但是A只有一個含參數(shù)的構(gòu)造器遣臼,這個時候B不知道怎么向A的構(gòu)造器傳遞參數(shù)。所以編譯器會報如下錯誤警告:
Implicit super constructor A() is undefined for default constructor. Must define an explicit constructor
這個時候就需要我們手動為A類傳入?yún)?shù)就行啦拾并。
class A {
A(int a) {
}
}
class B extends A{
B() {
super(1);
}
}
雖然編譯器強制你去初始化基類揍堰,并且要求你要在構(gòu)造器起始處就這么做,但是它并不監(jiān)督你必須將成員對象也初始化嗅义,因此在這一點上你自己必須時刻注意屏歹。
成員對象會在我們創(chuàng)建該類的對象的時候賦予一個值為“0”的初始值,所以我們不用擔(dān)心類似于空指針的異常之碗。而如果不先初始化父類的話蝙眶,就不能夠調(diào)用父類的方法和變量了。
如果Java基類擁有某個已經(jīng)被多次重載的方法名稱褪那,那么在導(dǎo)出類中重新定義該方法名稱并不會屏蔽其在基類中的任何版本械馆。
正如之前所提到的胖眷,一個方法是由其方法名和參數(shù)列表所決定的,子類中如果出現(xiàn)了與父類方法名或者形參列表不同的方法霹崎,那這就是子類獨有的方法珊搀,和父類的方法沒有任何關(guān)系,也就不會覆蓋掉父類的方法尾菇。
Java允許生成“空白
final
”境析,所謂空白final
是指被聲明為final但又未給定初始值的參數(shù)。無論什么情況下派诬,編譯器確崩拖空白final
在使用前都必須被初始化。但是空白final
在關(guān)鍵字final
上提供了更大的靈活性默赂。
final關(guān)鍵字在使用前必須被初始化沛鸵,那么我們可以在構(gòu)造器、初始化塊中對其初始化缆八。
類中所有的
private
方法都隱式的指定為final曲掰。由于無法使用private
方法,所以也就愛無法覆蓋它奈辰。
我們知道final
修飾一個方法是為了讓它不被子類重寫栏妖。如果我們在子類中創(chuàng)建一個方法名和形參列表都和父類方法一致的方法的話,編譯器就會報錯奖恰。但是如果使用private
而不是final
修飾父類方法的話吊趾,子類則不會報錯。
class A {
A(int a) {
}
private final void test() {
}
}
class B extends A{
B() {
super(1);
}
void test(int i){
}
}
因為這個時候在子類看來瑟啃,父類并沒有同名的方法论泛,父類中的private
方法對子類是不可見的。舉個例子蛹屿,公司A發(fā)明了一個新配方孵奶,但是不想申請專利,因為專利年限就幾十年蜡峰,公司A認(rèn)為這個配方能帶來幾百年的利益。然后公司B后來也發(fā)明了這個相似的配方朗恳,公司A就不能禁止公司B使用這個配方了湿颅,因為B完全是自己發(fā)明的,和A一點關(guān)系都沒有的粥诫。