深入了解Java程序執(zhí)行順序

首先做個(gè)測(cè)試:

public class Test1 {
    public static String name=get();
    public Test1() {
    }
    public static String get() {
        System.out.println("Test start");
        return "test name";
    }
    public static void main(String[] args) {
        System.out.println("main start");
        Test1 bb = new Test1();
    }
}

答案是啥鉴扫?

main start
test start

那你就out啦

正確答案是:

test start
main start

什么身害?不是從main方法執(zhí)行的嗎味悄?怎么回事呢?

Java程序運(yùn)行時(shí)塌鸯,第一件事情就是試圖訪問main方法侍瑟,因?yàn)閙ain相等于程序的入口,如果沒有main方法丙猬,程序?qū)o法啟動(dòng)涨颜,main方法更是占一個(gè)獨(dú)立的線程,找到main方法后淮悼,是不是就會(huì)執(zhí)行mian方法塊里的第一句話呢咐低?答案是不一定

分析:

    因?yàn)殪o態(tài)部分是依賴于類揽思,而不是依賴于對(duì)象存在的袜腥,所以靜態(tài)部分的加載優(yōu)先于對(duì)象存在。

當(dāng)找到main方法后钉汗,因?yàn)閙ain方法雖然是一個(gè)特殊的靜態(tài)方法羹令,但是還是靜態(tài)方法,此時(shí)JVM會(huì)加載main方法所在的類损痰,試圖找到類中其他靜態(tài)部分福侈,即首先會(huì)找main方法所在的類,然后會(huì)按照順序執(zhí)行類中的靜態(tài)代碼卢未,包括靜態(tài)變量肪凛,靜態(tài)方法和靜態(tài)代碼塊,靜態(tài)方法在不會(huì)主動(dòng)調(diào)用辽社,但會(huì)加載伟墙。靜態(tài)方法執(zhí)行完之后,才是動(dòng)態(tài)代碼的執(zhí)行滴铅,包括動(dòng)態(tài)屬性賦值和代碼塊

執(zhí)行順序大致分類:

1.靜態(tài)屬性戳葵,靜態(tài)方法聲明,靜態(tài)塊汉匙。

2.動(dòng)態(tài)屬性拱烁,普通方法聲明,構(gòu)造塊噩翠。

3.構(gòu)造方法戏自。

1.1 靜態(tài):

當(dāng)加載一個(gè)類時(shí),JVM會(huì)根據(jù)屬性的數(shù)據(jù)類型第一時(shí)間賦默認(rèn)值(一舉生成的)伤锚。然后再進(jìn)行靜態(tài)屬性初始化擅笔,并為靜態(tài)屬性分配內(nèi)存空間,靜態(tài)方法的聲明,靜態(tài)塊的加載剂娄,沒有優(yōu)先級(jí)之分蠢涝,按出現(xiàn)順序執(zhí)行,靜態(tài)部分僅僅加載一次阅懦。至此為止和二,必要的類都已經(jīng)加載完畢,對(duì)象就可以被創(chuàng)建了耳胎。

1.2 普通:

當(dāng)new一個(gè)對(duì)象時(shí)惯吕,此時(shí)會(huì)調(diào)用構(gòu)造方法,但是在調(diào)用構(gòu)造方法之前怕午,(此刻1.1已經(jīng)完成废登,除非被打斷而暫停)執(zhí)行動(dòng)態(tài)屬性定義并設(shè)置默認(rèn)值(一舉生成的)。然后動(dòng)態(tài)屬性初始化郁惜,分配內(nèi)存堡距,構(gòu)造塊,普通方法聲明(只是加載兆蕉,它不需要初始化羽戒,只有調(diào)用它時(shí)才分配內(nèi)存,當(dāng)方法執(zhí)行完畢后內(nèi)存立即釋放)虎韵,沒有優(yōu)先級(jí)之分易稠,按出現(xiàn)順序執(zhí)行。最后進(jìn)行構(gòu)造方法中賦值包蓝。當(dāng)再次創(chuàng)建一個(gè)對(duì)象驶社,不再執(zhí)行靜態(tài)部分,僅僅重復(fù)執(zhí)行普通部分测萎。

現(xiàn)在是否有些理解了呢亡电?

我們?cè)賮矸治鱿聞傞_始的測(cè)試題:

1、首先jvm找到main入口绳泉,加載整個(gè)類
2逊抡、找到整個(gè)類所有的靜態(tài)部分,包括 靜態(tài)變量和靜態(tài)代碼塊零酪,靜態(tài)方法 冒嫡,這里是先找到name,發(fā)現(xiàn)它調(diào)用了get()方法四苇,就先執(zhí)行g(shù)et方法孝凌,打印 test start ,返回值給name,執(zhí)行完成之后,發(fā)現(xiàn)沒有其他的靜態(tài)變量或代碼塊啦月腋,就執(zhí)行main方法蟀架,打印main start

再來道測(cè)試題:

class A {
    public A() {
        System.out.println("A的構(gòu)造方法");
    }

    public static int j = print();

    public static int print() {
        System.out.println("A print");
        return 521;
    }
}

public class Test1 extends A {
    public Test1() {
        System.out.println("Test1的構(gòu)造方法");
    }

    public static int k = print();

    public static int print() {
        System.out.println("Test print");
        return 522;
    }

    public static void main(String[] args) {
        System.out.println("main start");
        Test1 t1 = new Test1();
    }
}

運(yùn)行結(jié)果:

A print
Test print
main start
A的構(gòu)造方法
Test1的構(gòu)造方法

如果存在繼承關(guān)系瓣赂,會(huì)先執(zhí)行父類的靜態(tài)部分,再執(zhí)行子類的靜態(tài)部分片拍,再執(zhí)行父類的動(dòng)態(tài)部分煌集,再執(zhí)行子類的動(dòng)態(tài)部分

創(chuàng)建對(duì)象時(shí),依然會(huì)首先進(jìn)行動(dòng)態(tài)屬性進(jìn)行定義并設(shè)默認(rèn)值捌省,然后父類的構(gòu)造器才會(huì)被調(diào)用苫纤,其他一切都是先父類再子類(因?yàn)樽宇惖膕tatic初始化可能會(huì)依賴于父類成員能否被正確初始化),如果父類還有父類纲缓,依次類推卷拘,不管你是否打算產(chǎn)生一個(gè)該父類的對(duì)象,這都是自然發(fā)生的祝高。

最后再來一道終極測(cè)試題栗弟,這是阿里曾經(jīng)的測(cè)試題

public class Text {
    public static int k = 0;
    public static Text t1 = new Text("t1");
    public static Text t2 = new Text("t2");
    public static int i = print("i");
    public static int n = 99;
    public int j = print("j");

    {
        print("構(gòu)造塊");
    }
    static {
        print("靜態(tài)塊");
    }

    public Text(String str) {
        System.out.println((++k) + ":" + str + "   i=" + i + "    n=" + n);
        ++i;
        ++n;
    }

    public static int print(String str) {
        System.out.println((++k) + ":" + str + "   i=" + i + "    n=" + n);
        ++n;
        return ++i;
    }

    public static void main(String args[]) {
        Text t = new Text("init");
    }
}

有沒有生無可戀?工闺?乍赫??

運(yùn)行結(jié)果:

1:j   i=0    n=0
2:構(gòu)造塊   i=1    n=1
3:t1   i=2    n=2
4:j   i=3    n=3
5:構(gòu)造塊   i=4    n=4
6:t2   i=5    n=5
7:i   i=6    n=6
8:靜態(tài)塊   i=7    n=99
9:j   i=8    n=100
10:構(gòu)造塊   i=9    n=101
11:init   i=10    n=102

總結(jié):只要按照這個(gè)步驟斤寂,遇到這一類問題就可以解決了耿焊。

      1-3:類加載過程揪惦,不涉及構(gòu)造方法

      1-5: 實(shí)例化過程遍搞,涉及構(gòu)造方法

1.類中所有屬性的默認(rèn)值(一舉而成)

2. 父類靜態(tài)屬性初始化,靜態(tài)塊器腋,靜態(tài)方法的聲明(按出現(xiàn)順序執(zhí)行)

3. 子類靜態(tài)屬性初始化溪猿,靜態(tài)塊,靜態(tài)方法的聲明 (按出現(xiàn)順序執(zhí)行)

4. 調(diào)用父類的構(gòu)造方法纫塌,

首先父類的非靜態(tài)成員初始化诊县,構(gòu)造塊,普通方法的聲明(按出現(xiàn)順序執(zhí)行)

然后父類構(gòu)造方法

5. 調(diào)用子類的構(gòu)造方法措左,

首先子類的非靜態(tài)成員初始化依痊,構(gòu)造塊,普通方法的聲明(按出現(xiàn)順序執(zhí)行)

然后子類構(gòu)造方法

注意:

類加載過程中怎披,可能調(diào)用了實(shí)例化過程(因?yàn)閟tatic可以修飾方法胸嘁,屬性,代碼塊凉逛,內(nèi)部類)性宏,此時(shí)則會(huì)暫停類加載過程而先執(zhí)行實(shí)例化過程(被打斷),執(zhí)行結(jié)束再進(jìn)行類加載過程状飞,上面阿里那道面試題就是典型的暫停類加載毫胜。

簡(jiǎn)要分析:

1书斜、首先執(zhí)行靜態(tài)部分,先賦值k=0
2酵使、賦值 t1,發(fā)現(xiàn)t1涉及到實(shí)例化過程荐吉,先斷開類加載,執(zhí)行實(shí)例化過程
3口渔、實(shí)例化過程中稍坯,執(zhí)行類的動(dòng)態(tài)部分,就是j的賦值搓劫,它執(zhí)行了print方法瞧哟,所以先打印j ,i和n都會(huì)先初始化為0
4、j賦值完成之后枪向,繼續(xù)執(zhí)行動(dòng)態(tài)部分勤揩,就是類的代碼塊,打印 print("構(gòu)造塊")
5秘蛔、執(zhí)行完成后陨亡,沒動(dòng)態(tài)塊之后再執(zhí)行構(gòu)造函數(shù),至此整個(gè)實(shí)例化過程執(zhí)行完畢,t1賦值完成
6深员、t2按照t1執(zhí)行
7负蠕、然后賦值 i,n
8、然后再執(zhí)行靜態(tài)塊倦畅,執(zhí)行 print("靜態(tài)塊")遮糖,至此整個(gè)類加載過程完成
9、執(zhí)行main函數(shù)叠赐,賦值t,t和t1欲账、t2的執(zhí)行是一樣的

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市芭概,隨后出現(xiàn)的幾起案子赛不,更是在濱河造成了極大的恐慌,老刑警劉巖罢洲,帶你破解...
    沈念sama閱讀 219,270評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件踢故,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡惹苗,警方通過查閱死者的電腦和手機(jī)殿较,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鸽粉,“玉大人斜脂,你說我怎么就攤上這事〈セ” “怎么了帚戳?”我有些...
    開封第一講書人閱讀 165,630評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵玷或,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我片任,道長(zhǎng)偏友,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,906評(píng)論 1 295
  • 正文 為了忘掉前任对供,我火速辦了婚禮位他,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘产场。我一直安慰自己鹅髓,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評(píng)論 6 392
  • 文/花漫 我一把揭開白布京景。 她就那樣靜靜地躺著窿冯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪确徙。 梳的紋絲不亂的頭發(fā)上醒串,一...
    開封第一講書人閱讀 51,718評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音鄙皇,去河邊找鬼芜赌。 笑死,一個(gè)胖子當(dāng)著我的面吹牛伴逸,可吹牛的內(nèi)容都是我干的缠沈。 我是一名探鬼主播,決...
    沈念sama閱讀 40,442評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼违柏,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼博烂!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起漱竖,我...
    開封第一講書人閱讀 39,345評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎畜伐,沒想到半個(gè)月后馍惹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,802評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡玛界,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評(píng)論 3 337
  • 正文 我和宋清朗相戀三年万矾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片慎框。...
    茶點(diǎn)故事閱讀 40,117評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡良狈,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出笨枯,到底是詐尸還是另有隱情薪丁,我是刑警寧澤遇西,帶...
    沈念sama閱讀 35,810評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站严嗜,受9級(jí)特大地震影響粱檀,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜漫玄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評(píng)論 3 331
  • 文/蒙蒙 一茄蚯、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧睦优,春花似錦渗常、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至衡未,卻和暖如春尸执,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背缓醋。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評(píng)論 1 272
  • 我被黑心中介騙來泰國打工如失, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人送粱。 一個(gè)月前我還...
    沈念sama閱讀 48,377評(píng)論 3 373
  • 正文 我出身青樓褪贵,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親抗俄。 傳聞我的和親對(duì)象是個(gè)殘疾皇子脆丁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法动雹,內(nèi)部類的語法槽卫,繼承相關(guān)的語法,異常的語法胰蝠,線程的語...
    子非魚_t_閱讀 31,643評(píng)論 18 399
  • 前言 YY:Kitty茸塞,我最近在看Thinking in Java 這本書Kitty:喔躲庄?是么,你不是一直覺得那本...
    LilacZiyun閱讀 5,489評(píng)論 12 51
  • 一:java概述:1钾虐,JDK:Java Development Kit噪窘,java的開發(fā)和運(yùn)行環(huán)境,java的開發(fā)工...
    ZaneInTheSun閱讀 2,654評(píng)論 0 11
  • 父類 static 塊 1 執(zhí)行 父類 靜態(tài)成員staticSam1初始化 父類 靜態(tài)成員staticSam2初始...
    YCix閱讀 1,320評(píng)論 0 0
  • 現(xiàn)在大一效扫,長(zhǎng)了這么大倔监,第一次談戀愛直砂,haha是初戀,是很青澀丐枉,不同于其他人的是哆键,我的初戀是網(wǎng)戀+異地戀,我在吉林瘦锹,...
    Skyexin閱讀 238評(píng)論 0 1