Java代碼塊與代碼加載順序原理詳解
這篇文章主要介紹了Java代碼塊與代碼加載順序原理詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
本文首先介紹幾個(gè)基本的名次,然后介紹了三種代碼塊的特性和使用方法。
在面試大型公司時(shí),如果遇到大型國(guó)企或者大的互聯(lián)網(wǎng)私企,筆試中經(jīng)常遇到代碼塊和代碼加載順序的筆試題。這里做一個(gè)總結(jié),也方便各位小伙伴飆車不會(huì)飄。
名詞解釋
代碼塊
由 { } 包起來的代碼,稱為代碼塊
靜態(tài)代碼塊
由 static { } 包起來的代碼,稱為靜態(tài)代碼塊。
不同類型變量定義示例:
class Demo{ String x;// 非靜態(tài)成員變量,又稱為屬性,對(duì)該類不同的對(duì)象來說,屬性互不相同 static int y = 32;// 類變量,一個(gè)類中只有一個(gè)該變量,該類不同的對(duì)象共享同一個(gè)靜態(tài)成員變量 public static void main(String[] args){ int z = 0;// 局部變量,只在方法內(nèi)部可見,在方法結(jié)束后由垃圾收集器自動(dòng)回收 } }
局部代碼塊
位置:局部位置(方法內(nèi)部)。
作用:限定變量的生命周期,盡早釋放,節(jié)約內(nèi)存。
調(diào)用:調(diào)用其所在的方法時(shí)執(zhí)行。
方法中的局部代碼塊一般進(jìn)行一次性地調(diào)用,調(diào)用完立刻釋放空間,避免在接下來的調(diào)用過程中占用??臻g。??臻g內(nèi)存有限,方法調(diào)用可能會(huì)生成很多局部變量導(dǎo)致棧內(nèi)存不足,使用局部代碼塊可以避免此缺陷。
public class 局部代碼塊 { public static void go() { // 局部代碼塊 { int age = 30; System.out.print("go: " + age); } } public static void main(String[] args) { go(); } }
構(gòu)造代碼塊
位置:類成員的位置,即類中方法之外的位置。
作用:把多個(gè)構(gòu)造方法共同的部分提取出來,共用構(gòu)造代碼塊。
調(diào)用:每次調(diào)用構(gòu)造方法時(shí),都會(huì)優(yōu)先于構(gòu)造方法執(zhí)行,也就是每次new一個(gè)對(duì)象時(shí)自動(dòng)調(diào)用,實(shí)現(xiàn)對(duì)象初始化。
public class A { int i = 1; int initValue;//成員變量,初始化交給代碼塊來完成 A(){ System.out.println("構(gòu)造方法在代碼塊執(zhí)行后運(yùn)行"); } { System.out.println("代碼塊從上至下依次運(yùn)行"); //代碼塊的作用體現(xiàn)于此:在調(diào)用構(gòu)造方法之前,用某段代碼對(duì)成員變量進(jìn)行初始化。 //而不是在構(gòu)造方法調(diào)用時(shí)再進(jìn)行。 for (int i = 0;i < 100;i ++) { initValue += i; } } { System.out.println(initValue); System.out.println(i);//此時(shí)會(huì)打印1 int i = 2;//局部變量,和成員變量不沖突,但會(huì)優(yōu)先使用代碼塊的變量 System.out.println(i);//此時(shí)打印2 //System.out.println(j);//提示非法向后引用,因?yàn)榇藭r(shí)j的的初始化還沒開始。 } int j = 2; { System.out.println(j); System.out.println(i);//代碼塊中的變量運(yùn)行后自動(dòng)釋放,不會(huì)影響代碼塊之外的代碼 } } public class 構(gòu)造代碼塊 { @Test public void test() { A a = new A(); } }
執(zhí)行結(jié)果
代碼塊從上至下依次運(yùn)行 1 2 構(gòu)造方法在代碼塊執(zhí)行后運(yùn)行
靜態(tài)代碼塊
位置:類成員位置。
作用:對(duì)類進(jìn)行一些初始化,只加載一次。當(dāng)new多個(gè)對(duì)象時(shí),只有第一次會(huì)調(diào)用靜態(tài)代碼塊,因?yàn)殪o態(tài)代碼塊和類變量一樣,
是屬于類的,所有對(duì)象共享一份。
調(diào)用: new 一個(gè)對(duì)象時(shí)自動(dòng)調(diào)用。
public class 靜態(tài)代碼塊 { @Test public void test() { C c1 = new C(); C c2 = new C(); //結(jié)果,靜態(tài)代碼塊只會(huì)調(diào)用一次,類的所有對(duì)象共享該代碼塊 System.out.println("我是普通方法"); } } class C{ C(){ System.out.println("構(gòu)造方法調(diào)用"); } { System.out.println("代碼塊調(diào)用"); } static { System.out.println("靜態(tài)代碼塊調(diào)用"); } }
調(diào)用結(jié)果:
靜態(tài)代碼塊調(diào)用 代碼塊調(diào)用 構(gòu)造方法調(diào)用 代碼塊調(diào)用 構(gòu)造方法調(diào)用 我是普通方法
執(zhí)行順序 靜態(tài)代碼塊 —–> 構(gòu)造代碼塊 ——-> 構(gòu)造方法
筆試題
寫出下列程序輸出結(jié)果:
public class HelloA { public HelloA(){ System.out.println("HelloA"); } { System.out.println("I'm A class"); } static { System.out.println("static A"); } } public class HelloB extends HelloA { public HelloB(){ System.out.println("HelloB"); } { System.out.println("I'm B class"); } static { System.out.println("static B"); } public static void main(String[] args) { new HelloB(); } }
執(zhí)行結(jié)果:
分析:首先要知道靜態(tài)代碼塊是隨著類的加載而加載,而構(gòu)造代碼塊和構(gòu)造方法都是隨著對(duì)象的創(chuàng)建而加載。
1,在編譯HelloB.java時(shí),由于HelloB 繼承 HelloA,先加載了HelloA類,因此HelloA類的靜態(tài)代碼塊首先執(zhí)行,而后加載HelloB類,HelloB類的靜態(tài)代碼塊執(zhí)行,這沒什么好說的。
2,然后創(chuàng)建HelloB的對(duì)象,大家都知道構(gòu)造代碼塊優(yōu)先于構(gòu)造方法執(zhí)行,這時(shí)候問題來了,這時(shí)應(yīng)該先看HelloB類的構(gòu)造方法,HelloB類里的構(gòu)造方法里有一句隱式的super()首先被執(zhí)行,所以找到HelloA類的構(gòu)造方法,而HelloA類的構(gòu)造方法中也有一句隱式的super()執(zhí)行(調(diào)用Object類的構(gòu)造方法),并沒有什么返回結(jié)果,接下來才是在執(zhí)行HelloA類構(gòu)造方法的方法體前先執(zhí)行了HelloA類的構(gòu)造代碼塊(I'm A class),再執(zhí)行HelloA類構(gòu)造方法的方法體(也就是Hello A),最后又回到HelloB類的構(gòu)造方法中,這時(shí)HelloB類的super()已經(jīng)執(zhí)行完了,在執(zhí)行HelloB類構(gòu)造方法的方法體前先執(zhí)行HelloB類的構(gòu)造代碼塊(I'm B class),再執(zhí)行子類構(gòu)造方法的方法體(HellB)。
無繼承初始化順序:
有繼承初始化順序:
接下來看一道阿里筆試題:
public class B{ public static B t1 = new B(); public static B t2 = new B(); { System.out.println("構(gòu)造塊"); } static { System.out.println("靜態(tài)塊"); } public static void main(String[] args) { B t =new B(); } }
執(zhí)行結(jié)果:
總結(jié)
Java代碼初始化順序
由 static 關(guān)鍵字修飾的,如類變量和靜態(tài)代碼塊,將在類創(chuàng)建實(shí)例之前被初始化,而且是按順序從上到下依次被執(zhí)行。(類變量、靜態(tài)代碼塊)屬于類本身,不依賴于類的實(shí)例。
沒有 static 關(guān)鍵字修飾的(如:實(shí)例變量(非靜態(tài)變量)、非靜態(tài)代碼塊)初始化實(shí)際上是會(huì)被提取到類的構(gòu)造器中被執(zhí)行的,但是會(huì)比類構(gòu)造器中的代碼塊優(yōu)先執(zhí)行。實(shí)例變量、非靜態(tài)代碼塊的地位是相等的,它們將按順序被執(zhí)行。
容易混淆的一個(gè)知識(shí)點(diǎn)
靜態(tài)方法只允許直接訪問靜態(tài)成員,而實(shí)例方法中可以訪問靜態(tài)成員和實(shí)例成員,原因是類還沒有實(shí)例化,所以實(shí)例成員也沒有被創(chuàng)建,靜態(tài)方法中因此也不能用this。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
java數(shù)組的三種擴(kuò)容方式以及程序?qū)崿F(xiàn)詳解
這篇文章主要介紹了java數(shù)組的三種擴(kuò)容方式以及程序?qū)崿F(xiàn)詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12MybatisPlus保存、讀取MySQL中的json字段失敗問題及解決
這篇文章主要介紹了MybatisPlus保存、讀取MySQL中的json字段失敗問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07Servlet實(shí)現(xiàn)簡(jiǎn)單文件上傳功能
這篇文章主要為大家詳細(xì)介紹了Servlet實(shí)現(xiàn)簡(jiǎn)單文件上傳功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10Java-web中利用RSA進(jìn)行加密解密操作的方法示例
這篇文章主要給大家介紹了關(guān)于在Java-web中利用RSA進(jìn)行加密解密操作的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-08-08Spring?Security實(shí)現(xiàn)HTTP認(rèn)證
本文主要介紹了Spring?Security實(shí)現(xiàn)HTTP認(rèn)證,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧<BR>2022-06-06multi-catch和try-catch異常處理知識(shí)點(diǎn)詳解
在本篇文章里我們給大家分享了一篇關(guān)于multi-catch和try-catch異常處理知識(shí)點(diǎn)內(nèi)容,有需要的朋友們可以參考學(xué)習(xí)下。2019-11-11Spring動(dòng)態(tài)數(shù)據(jù)源實(shí)現(xiàn)讀寫分離詳解
這篇文章主要為大家詳細(xì)介紹了Spring動(dòng)態(tài)數(shù)據(jù)源實(shí)現(xiàn)讀寫分離,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07解決Springboot項(xiàng)目中很多頁面出現(xiàn)Whitelabel Error Page(404)的問題
最近在接手的前后端項(xiàng)目中發(fā)現(xiàn)其默認(rèn)路徑不是主機(jī)+端口(如:http://localhost:3453/)的形式,很多頁面的訪問是加了一個(gè)層級(jí),只要訪問頁面就會(huì)出現(xiàn)Whitelabel Error Page(404),所以本文給大家提供了解決方案,需要的朋友可以參考下2024-02-02統(tǒng)一建模語言_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要介紹了統(tǒng)一建模語言的相關(guān)知識(shí),非常不錯(cuò),具有參考借鑒價(jià)值,需要的的朋友參考下吧2017-06-06IntelliJ IDEA 構(gòu)建maven多模塊工程項(xiàng)目(詳細(xì)多圖)
這篇文章主要介紹了IntelliJ IDEA 構(gòu)建maven多模塊工程項(xiàng)目(詳細(xì)多圖),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06