Java中類(lèi)加載過(guò)程全面解析
類(lèi)文件加載的順序
1、先加載執(zhí)行父類(lèi)的靜態(tài)變量及靜態(tài)初始化塊(執(zhí)行先后順序按排列的先后順序)
2、再加載執(zhí)行本類(lèi)的靜態(tài)變量及靜態(tài)初始化塊
只要類(lèi)沒(méi)有被銷(xiāo)毀,靜態(tài)變量及靜態(tài)初始化塊只會(huì)執(zhí)行1次,后續(xù)再對(duì)該類(lèi)進(jìn)行其他操作也不會(huì)再執(zhí)行這兩個(gè)步驟。
類(lèi)實(shí)例創(chuàng)建過(guò)程
只有在調(diào)用new方法時(shí)才會(huì)創(chuàng)建類(lèi)的實(shí)例
1、按照上面類(lèi)文件加載的順序(類(lèi)已被加載則跳過(guò)此步)
2、父類(lèi)的非靜態(tài)變量及非靜態(tài)初始化塊
3、父類(lèi)的構(gòu)造方法
4、本類(lèi)的非靜態(tài)變量及非靜態(tài)初始化塊
5、本類(lèi)的構(gòu)造方法
4、類(lèi)實(shí)例銷(xiāo)毀時(shí)候,首先銷(xiāo)毀子類(lèi)部分,再銷(xiāo)毀父類(lèi)部分
靜態(tài)方法和非靜態(tài)方法都是被動(dòng)調(diào)用
即系統(tǒng)不會(huì)自動(dòng)調(diào)用執(zhí)行。所以用戶沒(méi)有調(diào)用時(shí)都不執(zhí)行,主要區(qū)別在于靜態(tài)方法可以直接用類(lèi)名直接調(diào)用(實(shí)例化對(duì)象也可以),而非靜態(tài)方法只能先實(shí)例化對(duì)象后才能調(diào)用。
相關(guān)概念
static關(guān)鍵字:
是一個(gè)修飾符,用于修飾成員(成員變量和成員函數(shù))
被修飾后的成員具備以下特點(diǎn):
隨著類(lèi)的加載而加載(類(lèi)一加載,靜態(tài)數(shù)據(jù)就立即在內(nèi)存中加載空間)
隨著類(lèi)的消失而消失,說(shuō)明它的生命周期最長(zhǎng)
優(yōu)先于對(duì)象存在(對(duì)象消失了,static還在)
靜態(tài)先存在,對(duì)象后存在
被所有對(duì)象所共享
節(jié)約內(nèi)存空間
當(dāng)成員被靜態(tài)修飾后,除了可以被對(duì)象調(diào)用外,還可以直接被類(lèi)名調(diào)用
寫(xiě)法:類(lèi)名.靜態(tài)成員
使用注意
靜態(tài)方法只能訪問(wèn)靜態(tài)成員(方法和變量)
非靜態(tài)方法既可以訪問(wèn)靜態(tài)也可以訪問(wèn)非靜態(tài)
靜態(tài)方法中不可以寫(xiě)this,super關(guān)鍵字
因?yàn)殪o態(tài)優(yōu)先于對(duì)象存在,所以靜態(tài)方法中不可以出現(xiàn)this
主函數(shù)是靜態(tài)的
publicstaticvoidmain(String[]args){}
何時(shí)使用靜態(tài)?
要從兩方面下手:因?yàn)殪o態(tài)修飾的內(nèi)容有成員變量和函數(shù)。
何時(shí)定義靜態(tài)變量(類(lèi)變量)
當(dāng)對(duì)象中出現(xiàn)共享數(shù)據(jù)時(shí),該數(shù)據(jù)被靜態(tài)所修飾。對(duì)象中的特有數(shù)據(jù)要定義成非靜態(tài)存在于堆內(nèi)存中。
何時(shí)定義靜態(tài)函數(shù)
當(dāng)功能內(nèi)部沒(méi)有訪問(wèn)到非靜態(tài)數(shù)據(jù)(對(duì)象特有數(shù)據(jù)),該功能可以定義成靜態(tài)。
靜態(tài)利弊
利:
1、對(duì)對(duì)象的共享數(shù)據(jù)單獨(dú)空間的存儲(chǔ),節(jié)省空間。沒(méi)有必要每個(gè)對(duì)象都存儲(chǔ)一份。
2、可以直接被類(lèi)名調(diào)用
弊:
1、生命周期過(guò)長(zhǎng)
2、訪問(wèn)出現(xiàn)局限性(只能訪問(wèn)靜態(tài))
內(nèi)存結(jié)構(gòu)
Java程序在運(yùn)行時(shí),需要在內(nèi)存中的分配空間。為了提高運(yùn)算效率,有對(duì)空間進(jìn)行了不同區(qū)域的劃分,因?yàn)槊恳黄瑓^(qū)域都有特定的處理數(shù)據(jù)方式和內(nèi)存管理方式。
棧內(nèi)存
用于存儲(chǔ)局部變量當(dāng)數(shù)據(jù)使用完,所占空間會(huì)自動(dòng)釋放
堆內(nèi)存
數(shù)組和對(duì)象(實(shí)體),通過(guò)new建立的實(shí)例都存放在堆內(nèi)存中(成員變量隨著對(duì)象的建立而建立,存在于對(duì)象所在的堆內(nèi)存中)每一個(gè)實(shí)體都有內(nèi)存地址值(變量通過(guò)地址引用)實(shí)體中的變量都有默認(rèn)初始化值實(shí)體不再被使用,會(huì)在不確定的時(shí)間內(nèi)被垃圾回收器回收(垃圾回收機(jī)制)
方法區(qū),本地方法區(qū),寄存器
驗(yàn)證
加載順序 | 父類(lèi)靜態(tài)變量=1 | 父類(lèi)非靜態(tài)變量=1 | 子類(lèi)靜態(tài)變量=1 | 子類(lèi)非靜態(tài)變量=1 |
---|---|---|---|---|
【父類(lèi)調(diào)用父類(lèi)靜態(tài)方法】 | Parent.pStaticMethod(); | |||
父類(lèi)靜態(tài)初始化塊一 | 2 | |||
父類(lèi)靜態(tài)初始化塊二 | 3 | |||
父類(lèi)靜態(tài)方法 | 4 | |||
【子類(lèi)調(diào)用子類(lèi)靜態(tài)方法】 | Child.cStaticMethod(); | |||
子類(lèi)靜態(tài)初始化塊一 | 5 | 2 | ||
子類(lèi)靜態(tài)初始化塊二 | 6 | 3 | ||
子類(lèi)靜態(tài)方法 | 7 | 4 | ||
【子類(lèi)實(shí)例化】 | Child c=new Child(); | |||
父類(lèi)非靜態(tài)初始化塊一 | 8 | 2 | ||
父類(lèi)非靜態(tài)初始化塊二 | 9 | 3 | ||
父類(lèi)構(gòu)造方法 | 10 | 4 | ||
子類(lèi)非靜態(tài)初始化塊一 | 11 | 5 | 5 | 2 |
子類(lèi)非靜態(tài)初始化塊二 | 12 | 6 | 6 | 3 |
子類(lèi)構(gòu)造方法 | 13 | 7 | 7 | 4 |
【父類(lèi)實(shí)例化子類(lèi)對(duì)象】 | Parent p=new Child(); | |||
父類(lèi)非靜態(tài)初始化塊一 | 14 | 2 | ||
父類(lèi)非靜態(tài)初始化塊二 | 15 | 3 | ||
父類(lèi)構(gòu)造方法 | 16 | 4 | ||
子類(lèi)非靜態(tài)初始化塊一 | 17 | 5 | 8 | 2 |
子類(lèi)非靜態(tài)初始化塊二 | 18 | 6 | 9 | 3 |
子類(lèi)構(gòu)造方法 | 19 | 7 | 10 | 4 |
加載順序 | 父類(lèi)靜態(tài)變量=1 | 父類(lèi)非靜態(tài)變量=1 | 子類(lèi)靜態(tài)變量=1 | 子類(lèi)非靜態(tài)變量=1 |
---|---|---|---|---|
【子類(lèi)實(shí)例化】 | Child c=new Child(); | |||
父類(lèi)靜態(tài)初始化塊一 | 2 | |||
父類(lèi)靜態(tài)初始化塊二 | 3 | |||
子類(lèi)靜態(tài)初始化塊一 | 4 | 2 | ||
子類(lèi)靜態(tài)初始化塊二 | 5 | 3 | ||
父類(lèi)非靜態(tài)初始化塊一 | 6 | 2 | ||
父類(lèi)非靜態(tài)初始化塊二 | 7 | 3 | ||
父類(lèi)構(gòu)造方法 | 8 | 4 | ||
子類(lèi)非靜態(tài)初始化塊一 | 9 | 5 | 4 | 2 |
子類(lèi)非靜態(tài)初始化塊二 | 10 | 6 | 5 | 3 |
子類(lèi)構(gòu)造方法 | 11 | 7 | 6 | 4 |
【父類(lèi)實(shí)例化子類(lèi)對(duì)象】 | Parent p=new Child(); | |||
父類(lèi)非靜態(tài)初始化塊一 | 12 | 2 | ||
父類(lèi)非靜態(tài)初始化塊二 | 13 | 3 | ||
父類(lèi)構(gòu)造方法 | 14 | 4 | ||
子類(lèi)非靜態(tài)初始化塊一 | 15 | 5 | 7 | 2 |
子類(lèi)非靜態(tài)初始化塊二 | 16 | 6 | 8 | 3 |
子類(lèi)構(gòu)造方法 | 17 | 7 | 9 | 4 |
【父類(lèi)調(diào)用父類(lèi)靜態(tài)方法】 | Parent.pStaticMethod(); | |||
父類(lèi)靜態(tài)方法 | 18 | |||
【子類(lèi)調(diào)用子類(lèi)靜態(tài)方法】 | Child.cStaticMethod(); | |||
子類(lèi)靜態(tài)方法 | 19 | 10 |
public class ClassTest { public static void main (String args[]) { System.out.println("【子類(lèi)實(shí)例化】|Child c=new Child();"); Child c=new Child(); System.out.println("【父類(lèi)實(shí)例化子類(lèi)對(duì)象】|Parent p=new Child();"); Parent p=new Child(); System.out.println("【父類(lèi)調(diào)用父類(lèi)靜態(tài)方法】|Parent.pStaticMethod();"); Parent.pStaticMethod(); System.out.println("【子類(lèi)調(diào)用子類(lèi)靜態(tài)方法】|Child.cStaticMethod();"); Child.cStaticMethod(); } }
public class ClassTest2 { public static void main (String args[]) { System.out.println("【父類(lèi)調(diào)用父類(lèi)靜態(tài)方法】|Parent.pStaticMethod();"); Parent.pStaticMethod(); System.out.println("【子類(lèi)調(diào)用子類(lèi)靜態(tài)方法】|Child.cStaticMethod();"); Child.cStaticMethod(); System.out.println("【子類(lèi)實(shí)例化】|Child c=new Child();"); Child c=new Child(); System.out.println("【父類(lèi)實(shí)例化子類(lèi)對(duì)象】|Parent p=new Child();"); Parent p=new Child(); } }
public class Parent { // 父類(lèi)靜態(tài)變量 static int m = 1; // 父類(lèi)非靜態(tài)變量 int n = 1; // 靜態(tài)語(yǔ)句塊1 static { m++; // j++; 父類(lèi)非靜態(tài)變量不能在靜態(tài)語(yǔ)句塊中使用 System.out.println("父類(lèi)靜態(tài)初始化塊一|" + m); } // 靜態(tài)語(yǔ)句塊2 static { m++; System.out.println("父類(lèi)靜態(tài)初始化塊二|" + m); } // 構(gòu)造函數(shù) public Parent() { m++; n++; System.out.println("父類(lèi)構(gòu)造方法|" + m + "|" + n); } // 非靜態(tài)語(yǔ)句塊 { m++; n++; System.out.println("父類(lèi)非靜態(tài)初始化塊一|" + m + "|" + n); } // 非靜態(tài)語(yǔ)句塊 { m++; n++; System.out.println("父類(lèi)非靜態(tài)初始化塊二|" + m + "|" + n); } // 非靜態(tài)方法 public void pMethod() { m++; n++; System.out.println("父類(lèi)非靜態(tài)方法|" + m + "|" + n); return; } // 靜態(tài)方法 public static void pStaticMethod() { m++; // j++; 父類(lèi)非靜態(tài)變量不能在靜態(tài)方法中使用 System.out.println("父類(lèi)靜態(tài)方法|" + m); return; } @Override protected void finalize() throws Throwable { super.finalize(); System.out.println("銷(xiāo)毀父類(lèi)|"); } }
public class Child extends Parent { // 靜態(tài)變量 static int i = 1; // 非靜態(tài)變量 int j = 1; // 靜態(tài)語(yǔ)句塊1 static { m++; i++; // j++; 非靜態(tài)變量不能在靜態(tài)語(yǔ)句塊中使用 System.out.println("子類(lèi)靜態(tài)初始化塊一 " + "|" + m + "||" + i); } // 靜態(tài)語(yǔ)句塊2 static { m++; i++; System.out.println("子類(lèi)靜態(tài)初始化塊二 " + "|" + m + "||" + i); } // 構(gòu)造函數(shù) public Child() { m++; n++; i++; j++; System.out.println("子類(lèi)構(gòu)造方法 " + "|" + m + "|" + n + "|" + i + "|" + j); } // 非靜態(tài)語(yǔ)句塊 { m++; n++; i++; j++; System.out.println("子類(lèi)非靜態(tài)初始化塊一" + "|" + m + "|" + n + "|" + i + "|" + j); } // 非靜態(tài)語(yǔ)句塊 { m++; n++; i++; j++; System.out.println("子類(lèi)非靜態(tài)初始化塊二" + "|" + m + "|" + n + "|" + i + "|" + j); } // 非靜態(tài)方法 public void pMethod() { m++; n++; i++; j++; System.out.println("子類(lèi)繼承非靜態(tài)方法" + "|" + m + "|" + n + "|" + i + "|" + j); return; } // 靜態(tài)方法 public static void pStaticMethod() {// 靜態(tài)方法不能被繼承 m++; i++; // j++; 非靜態(tài)變量不能在靜態(tài)方法中使用 return; } // 非靜態(tài)方法 public void cMethod() { m++; n++; i++; j++; System.out.println("子類(lèi)非靜態(tài)方法" + "|" + m + "|" + n + "|" + i + "|" + j); return; } // 靜態(tài)方法 public static void cStaticMethod() { m++; i++; // j++; 非靜態(tài)變量不能在靜態(tài)方法中使用 System.out.println("子類(lèi)靜態(tài)方法 " + "|" + m + "||" + i); return; } @Override protected void finalize() throws Throwable { super.finalize(); System.out.println("銷(xiāo)毀子類(lèi)|"); } }
總結(jié)
以上就是本文關(guān)于Java中類(lèi)加載過(guò)程全面解析的全部?jī)?nèi)容,希望對(duì)大家有所幫助。如有問(wèn)題可以隨時(shí)留言,小編會(huì)及時(shí)回復(fù)大家的。期待您的寶貴意見(jiàn)。
相關(guān)文章
一篇文章帶你搞定SpringBoot不重啟項(xiàng)目實(shí)現(xiàn)修改靜態(tài)資源
這篇文章主要介紹了一篇文章帶你搞定SpringBoot不重啟項(xiàng)目實(shí)現(xiàn)修改靜態(tài)資源,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09Java命令行運(yùn)行錯(cuò)誤之找不到或無(wú)法加載主類(lèi)問(wèn)題的解決方法
這篇文章主要給大家介紹了關(guān)于Java命令行運(yùn)行錯(cuò)誤之找不到或無(wú)法加載主類(lèi)問(wèn)題的解決方法,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2022-01-01IDEA啟動(dòng)Springboot報(bào)錯(cuò):無(wú)效的目標(biāo)發(fā)行版:17 的解決辦法
這篇文章主要給大家介紹了IDEA啟動(dòng)Springboot報(bào)錯(cuò):無(wú)效的目標(biāo)發(fā)行版:17 的解決辦法,文中通過(guò)代碼示例和圖文講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-02-02Activiti進(jìn)階之組任務(wù)實(shí)現(xiàn)示例詳解
這篇文章主要為大家介紹了Activiti進(jìn)階之組任務(wù)實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08Spring啟動(dòng)后獲取所有擁有特定注解的Bean實(shí)例代碼
這篇文章主要介紹了Spring啟動(dòng)后獲取所有擁有特定注解的Bean實(shí)例代碼,分享了相關(guān)代碼示例,小編覺(jué)得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-02-02JPA中@JoinColumn的name和referencedColumnName屬性的區(qū)別及說(shuō)明
這篇文章主要介紹了JPA中@JoinColumn的name和referencedColumnName屬性的區(qū)別及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-05-05Java 實(shí)戰(zhàn)項(xiàng)目錘煉之小區(qū)物業(yè)管理系統(tǒng)的實(shí)現(xiàn)流程
讀萬(wàn)卷書(shū)不如行萬(wàn)里路,只學(xué)書(shū)上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實(shí)戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+SSM+jsp+mysql+maven實(shí)現(xiàn)一個(gè)小區(qū)物業(yè)管理系統(tǒng),大家可以在過(guò)程中查缺補(bǔ)漏,提升水平2021-11-11springboot3.x中Jakarta包無(wú)法引入的問(wèn)題
最近想將一些項(xiàng)目升級(jí)到springboot3.x和java17的時(shí)候,發(fā)現(xiàn)項(xiàng)目依賴(lài)中有Jakarta的包,但是代碼標(biāo)紅提示沒(méi)有相關(guān)的類(lèi),本文就來(lái)介紹一下解決方法,感興趣的可以了解一下2024-02-02System.getProperty(user.dir)定位問(wèn)題解析
System.getProperty(user.dir) 獲取的是啟動(dòng)項(xiàng)目的容器位置,用IDEA是項(xiàng)目的根目錄,部署在tomcat上是tomcat的啟動(dòng)路徑,即tomcat/bin的位置,這篇文章主要介紹了System.getProperty(user.dir)定位問(wèn)題,需要的朋友可以參考下2023-05-05