詳解java中繼承關系類加載順序問題
詳解java中繼承關系類加載順序問題
實例代碼:
/**
* Created by fei on 2017/5/31.
*/
public class SonClass extends ParentClass{
public SonClass(){
System.out.println("SonClass's constructor");
}
{ System.out.println("SonClass's block");}
static {
System.out.println("SonClass's static block ");
}
public static void main(String[] args) {
System.out.println("------ main start ------ ");
new SonClass();
System.out.println("------ main end ------ ");
}
}
class ParentClass{
public ParentClass(){
System.out.println("ParentClass's constructor");
}
{ System.out.println("ParentClass's block");}
static {
System.out.println("ParentClass's static block ");
}
}
運行結果:
ParentClass's static block SonClass's static block ------ main start ------ ParentClass's block ParentClass's constructor SonClass's block SonClass's constructor ------ main end ------
根據運行結果,一目了然,在執(zhí)行 main 方法中 new SonClass() 之前,就在類加載之后執(zhí)行了類中 static 代碼塊。然后再進入main方法,執(zhí)行new操作,當然顯而易見,在執(zhí)行new子類操作的時候,是要先進行其父類的構造,即先執(zhí)行父類的構造代碼塊(代碼中只用大括號包裹的那段代碼)以及構造函數 ,然后再執(zhí)行子類的構造代碼塊以及構造函數。
修改一下代碼,再來看看運行的結果:
/**
* Created by fei on 2017/5/31.
*/
public class SonClass extends ParentClass{
ParentClass parentClass;
public SonClass(){
System.out.println("1");
}
public SonClass(String name){
System.out.println("2");
this.name = name;
parentClass = new ParentClass("FEI");
}
public static void main(String[] args) {
System.out.println("------ main start ------ ");
new SonClass("fei");
System.out.println("------ main end ------ ");
}
}
class ParentClass{
String name ;
public ParentClass(){
System.out.println("3");
}
public ParentClass(String name){
System.out.println("4");
this.name = name ;
}
}
運行的順序是:
------ main start ------ 3 2 4 ------ main end ------
第一個規(guī)則:子類的構造過程中,必須調用其父類的構造方法。一個類,如果我們不寫構造方法,那么編譯器會幫我們加上一個默認的構造方法(就是沒有參數的構造方法),但是如果你自己寫了構造方法,那么編譯器就不會給你添加了,所以有時候當你new一個子類對象的時候,肯定調用了子類的構造方法,但是如果在子類構造方法中我們并沒有顯示的調用基類的構造方法,如:super(); 這樣就會調用父類沒有參數的構造方法。
第二個規(guī)則:如果子類的構造方法中既沒有顯示的調用基類構造方法,而基類中又沒有無參的構造方法,則編譯出錯,所以,通常我們需要顯示的:super(參數列表),來調用父類有參數的構造函數,此時無參的構造函數就不會被調用。
總之,一句話:子類沒有顯示調用父類構造函數,不管子類構造函數是否帶參數都默認調用父類無參的構造函數,若父類沒有則編譯出錯。
還是兩個類,我們再更改一下。
/**
* Created by fei on 2017/5/31.
*/
public class SonClass extends ParentClass{
private String name = "SonClass";
public SonClass() {
printName();
}
public void printName() {
System.out.println("SonClass print name: " + name);
}
public static void main(String[] args){
new SonClass();
}
}
class ParentClass{
private String name = "ParentClass";
public ParentClass() {
//System.out.println(this.getClass());
printName();
}
public void printName() {
System.out.println("ParentClass print name: " + name);
}
}
看了上面的兩個例子,最后這個例子就很容易被迷惑,可能有人會覺得運行結果是類似這樣的:
ParentClass print name: ParentClass SonClass print name: SonClass
或者是:
ParentClass print name: SonClass SonClass print name: SonClass
但真正的結果是這樣的:
SonClass print name: null SonClass print name: SonClass
為什么會這樣,其實只要打開代碼中父類構造器中的這句注釋,就很容易理解了:System.out.println(this.getClass())
結果是:
class SonClass
沒錯,父類中的this引用是子類實例對象,所以在父類構造函數里調用的還是子類的printName()方法。具體原因也并我能十分肯定,我個人淺見,是因為雖然我們調用了父類的構造方法,但是我們并沒有實例化出父類的實例對象,所以this還是指向的是子類的引用。
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
相關文章
maven-assembly-plugin報紅無法加載報錯:Plugin?‘maven-assembly-plugin
maven-assembly-plugin是一個常用的打包插件,但是在使用過程中經常會遇到各種報錯,本文就來介紹一下maven-assembly-plugin報紅無法加載報錯,具有一定的參考價值2023-08-08
Java之多個線程順序循環(huán)執(zhí)行的幾種實現
這篇文章主要介紹了Java之多個線程順序循環(huán)執(zhí)行的幾種實現方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-09-09

