詳解java中繼承關(guān)系類加載順序問題
詳解java中繼承關(guān)系類加載順序問題
實(shí)例代碼:
/** * 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 "); } }
運(yùn)行結(jié)果:
ParentClass's static block SonClass's static block ------ main start ------ ParentClass's block ParentClass's constructor SonClass's block SonClass's constructor ------ main end ------
根據(jù)運(yùn)行結(jié)果,一目了然,在執(zhí)行 main 方法中 new SonClass() 之前,就在類加載之后執(zhí)行了類中 static 代碼塊。然后再進(jìn)入main方法,執(zhí)行new操作,當(dāng)然顯而易見,在執(zhí)行new子類操作的時(shí)候,是要先進(jìn)行其父類的構(gòu)造,即先執(zhí)行父類的構(gòu)造代碼塊(代碼中只用大括號(hào)包裹的那段代碼)以及構(gòu)造函數(shù) ,然后再執(zhí)行子類的構(gòu)造代碼塊以及構(gòu)造函數(shù)。
修改一下代碼,再來(lái)看看運(yùn)行的結(jié)果:
/** * 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 ; } }
運(yùn)行的順序是:
------ main start ------ 3 2 4 ------ main end ------
第一個(gè)規(guī)則:子類的構(gòu)造過(guò)程中,必須調(diào)用其父類的構(gòu)造方法。一個(gè)類,如果我們不寫構(gòu)造方法,那么編譯器會(huì)幫我們加上一個(gè)默認(rèn)的構(gòu)造方法(就是沒有參數(shù)的構(gòu)造方法),但是如果你自己寫了構(gòu)造方法,那么編譯器就不會(huì)給你添加了,所以有時(shí)候當(dāng)你new一個(gè)子類對(duì)象的時(shí)候,肯定調(diào)用了子類的構(gòu)造方法,但是如果在子類構(gòu)造方法中我們并沒有顯示的調(diào)用基類的構(gòu)造方法,如:super(); 這樣就會(huì)調(diào)用父類沒有參數(shù)的構(gòu)造方法。
第二個(gè)規(guī)則:如果子類的構(gòu)造方法中既沒有顯示的調(diào)用基類構(gòu)造方法,而基類中又沒有無(wú)參的構(gòu)造方法,則編譯出錯(cuò),所以,通常我們需要顯示的:super(參數(shù)列表),來(lái)調(diào)用父類有參數(shù)的構(gòu)造函數(shù),此時(shí)無(wú)參的構(gòu)造函數(shù)就不會(huì)被調(diào)用。
總之,一句話:子類沒有顯示調(diào)用父類構(gòu)造函數(shù),不管子類構(gòu)造函數(shù)是否帶參數(shù)都默認(rèn)調(diào)用父類無(wú)參的構(gòu)造函數(shù),若父類沒有則編譯出錯(cuò)。
還是兩個(gè)類,我們?cè)俑囊幌隆?/p>
/** * 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); } }
看了上面的兩個(gè)例子,最后這個(gè)例子就很容易被迷惑,可能有人會(huì)覺得運(yùn)行結(jié)果是類似這樣的:
ParentClass print name: ParentClass SonClass print name: SonClass
或者是:
ParentClass print name: SonClass SonClass print name: SonClass
但真正的結(jié)果是這樣的:
SonClass print name: null SonClass print name: SonClass
為什么會(huì)這樣,其實(shí)只要打開代碼中父類構(gòu)造器中的這句注釋,就很容易理解了:System.out.println(this.getClass())
結(jié)果是:
class SonClass
沒錯(cuò),父類中的this引用是子類實(shí)例對(duì)象,所以在父類構(gòu)造函數(shù)里調(diào)用的還是子類的printName()方法。具體原因也并我能十分肯定,我個(gè)人淺見,是因?yàn)殡m然我們調(diào)用了父類的構(gòu)造方法,但是我們并沒有實(shí)例化出父類的實(shí)例對(duì)象,所以this還是指向的是子類的引用。
感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!
相關(guān)文章
maven-assembly-plugin報(bào)紅無(wú)法加載報(bào)錯(cuò):Plugin?‘maven-assembly-plugin
maven-assembly-plugin是一個(gè)常用的打包插件,但是在使用過(guò)程中經(jīng)常會(huì)遇到各種報(bào)錯(cuò),本文就來(lái)介紹一下maven-assembly-plugin報(bào)紅無(wú)法加載報(bào)錯(cuò),具有一定的參考價(jià)值2023-08-08MyBatis-Plus實(shí)現(xiàn)條件查詢的三種格式例舉詳解
本文主要介紹了MyBatis-Plus三中條件查詢格式的示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08Java之多個(gè)線程順序循環(huán)執(zhí)行的幾種實(shí)現(xiàn)
這篇文章主要介紹了Java之多個(gè)線程順序循環(huán)執(zhí)行的幾種實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09Presto支持Elasticsearch數(shù)據(jù)源配置詳解
這篇文章主要為大家介紹了Presto支持Elasticsearch數(shù)據(jù)源配置詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12Java面試之動(dòng)態(tài)規(guī)劃與組合數(shù)
這篇文章主要介紹了Java面試之動(dòng)態(tài)規(guī)劃與組合數(shù)的相關(guān)知識(shí),非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-09-09java web實(shí)現(xiàn)郵箱激活與忘記密碼
這篇文章主要為大家詳細(xì)介紹了java web實(shí)現(xiàn)郵箱激活與忘記密碼、重置密碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-02-02