国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|

服務(wù)器之家 - 編程語(yǔ)言 - JAVA教程 - Java中return和finally到底哪個(gè)先執(zhí)行

Java中return和finally到底哪個(gè)先執(zhí)行

2020-10-28 21:42今日頭條Java成長(zhǎng)催化師 JAVA教程

本章節(jié)我們從字節(jié)碼的角度來(lái)探究下return和finally到底哪個(gè)先執(zhí)行。下面先來(lái)看一段簡(jiǎn)單地源碼。

Java中return和finally到底哪個(gè)先執(zhí)行

本章節(jié)我們從字節(jié)碼的角度來(lái)探究下returnfinally到底哪個(gè)先執(zhí)行。下面先來(lái)看一段簡(jiǎn)單地源碼:

public class ReturnFinallyDemo { 

    public static void main(String[] args) { 

        System.out.println(case1()); 

    } 

 

    public static int case1() { 

        int x; 

        try { 

            x = 1; 

            return x; 

        } finally { 

            x = 3; 

        } 

    } 

 

# 輸出 

上述代碼的輸出可以簡(jiǎn)單地得出結(jié)論:return在finally之前執(zhí)行,我們來(lái)看下字節(jié)碼層面上發(fā)生了什么事情。下面截取case1方法的部分字節(jié)碼,并且對(duì)照源碼,將每個(gè)指令的含義注釋在后面:

iconst_1 // 將常量1推入操作數(shù)棧頂  

istore_0 // 彈出棧頂元素(1),保存到局部變量表slot[0],此時(shí)slot[0]=1。這兩條指令對(duì)應(yīng)源碼:x = 1;  

iload_0 // 將局部變量表slot[0]的值推入操作數(shù)棧頂,也就是說(shuō)把上面x的值推入棧頂  

istore_1 // 彈出棧頂元素(1),保存到局部變量表slot[1],此時(shí)slot[1]=1。其實(shí),此時(shí)就已經(jīng)把要return的值準(zhǔn)備好了  

iconst_3 // 將常量3推入操作數(shù)棧頂,這一條指令開(kāi)始,其實(shí)是開(kāi)始執(zhí)行finally中的代碼了  

istore_0 // 彈出棧頂元素(3),保存到局部變量表slot[0],此時(shí)slot[0]=3。這兩個(gè)指令對(duì)應(yīng)源碼:x = 3;這里要注意的是,雖然都是更新了x的值,但是finally中的x和try中x的賦值,保存在了不同的局部變量表中 

iload_1 // 將局部變量表slot[1]的值推入操作數(shù)棧頂,此時(shí)棧頂元素的值為1,是第3行指令保存的值 

 

ireturn // 將操作數(shù)棧頂?shù)闹捣祷亟o調(diào)用方 

從字節(jié)碼來(lái)看,似乎又是finally的代碼先執(zhí)行了,因?yàn)閕return指令確實(shí)是在最后執(zhí)行的,所以返回什么樣的值不在于誰(shuí)先執(zhí)行,而在于ireturn指令返回的操作數(shù)棧頂?shù)脑厥呛螘r(shí)保存的。在上述代碼環(huán)境中,是try代碼塊中給x賦值的版本,也就是緊接著return語(yǔ)句后面的x所保存的版本。

下面再來(lái)看一個(gè)稍微復(fù)雜點(diǎn)的場(chǎng)景:

public static int case2() { 

    int x; 

    try { 

        x = 1; 

        return ++x; 

    } finally { 

        x = 3; 

    } 

 

# 輸出 

有了上面的分析,這個(gè)就很好理解了,我們還是來(lái)看下字節(jié)碼:

iconst_1 // 將常量1推入操作數(shù)棧頂 

istore_0 // 彈出棧頂元素(1),保存到局部變量表slot[0],此時(shí)slot[0]=1。這兩條指令對(duì)應(yīng)源碼:x = 1; 

iinc          0, 1 // 對(duì)局部變量表slot[0]進(jìn)行自增(+1)操作,此時(shí)slot[0]=2,對(duì)應(yīng)源碼:++x;所以,可以看出return后面的表達(dá)式先執(zhí)行 

iload_0 // 將局部變量表slot[0]的值推入操作數(shù)棧頂,也就是說(shuō)把上面x的值(2)推入棧頂 

istore_1 // 彈出棧頂元素(2),保存到局部變量表slot[1],此時(shí)slot[1]=2。其實(shí),此時(shí)就已經(jīng)把要return的值準(zhǔn)備好了 

iconst_3 // 將常量3推入操作數(shù)棧頂,這一條指令開(kāi)始,其實(shí)是開(kāi)始執(zhí)行finally中的代碼了 

istore_0 // 彈出棧頂元素(3),保存到局部變量表slot[0],此時(shí)slot[0]=3。這兩個(gè)指令對(duì)應(yīng)源碼:x = 3;這里要注意的是,雖然都是更新了x的值,但是finally中的x和try中x的賦值,保存在了不同的局部變量表中 

iload_1 // 將局部變量表slot[1]的值推入操作數(shù)棧頂,此時(shí)棧頂元素的值為2,是第6行指令保存的值,也就是經(jīng)過(guò)++x之后的值 

ireturn // 將操作數(shù)棧頂?shù)闹捣祷亟o調(diào)用方 

從上述代碼可以看出,return后面的指令先執(zhí)行,然后保存到局部變量表,接著執(zhí)行finally中的語(yǔ)句,最后執(zhí)行return指令本身。

總結(jié)一下,return指令是最后執(zhí)行的,如果return后面有表達(dá)式,則執(zhí)行完表達(dá)式之后就執(zhí)行finally中的語(yǔ)句,最后再執(zhí)行return指令。所以說(shuō)finally和return到底哪個(gè)先執(zhí)行:return指令后面如果有表達(dá)式或方法調(diào)用的話,先執(zhí)行,然后執(zhí)行finally,最后執(zhí)行return指令。就像上面的程序演示的結(jié)果,不能光從x的賦值來(lái)看最終返回結(jié)果,從指令層面看,兩次對(duì)x的賦值,保存在局部變量表的位置不一樣。

最后,再來(lái)看一個(gè)平時(shí)不會(huì)這么去寫(xiě)的場(chǎng)景:

public static int case3() { 

    int x; 

    try { 

        x = 1; 

        return ++x; 

    } finally { 

        x = 3; 

        return x; 

    } 

# 輸出 

這是一個(gè)finally返回結(jié)果的示例,平時(shí)不建議這么寫(xiě),我們同樣從字節(jié)碼的角度來(lái)分析下:

iconst_1 // 將常量1推入操作數(shù)棧頂 

istore_0 // 彈出棧頂元素(1),保存到局部變量表slot[0],此時(shí)slot[0]=1。這兩條指令對(duì)應(yīng)源碼:x = 1; 

iinc          0, 1 // 對(duì)局部變量表slot[0]進(jìn)行自增(+1)操作,此時(shí)slot[0]=2,對(duì)應(yīng)源碼:++x;所以,可以看出return后面的表達(dá)式先執(zhí)行 

iload_0  // 將局部變量表slot[0]的值推入操作數(shù)棧頂,也就是說(shuō)把上面x的值(2)推入棧頂 

istore_1 // 彈出棧頂元素(2),保存到局部變量表slot[1],此時(shí)slot[1]=2。 

iconst_3 // 將常量3推入操作數(shù)棧頂,這一條指令開(kāi)始,其實(shí)是開(kāi)始執(zhí)行finally中的代碼了 

istore_0 // 彈出棧頂元素(3),保存到變量表slot[0],此時(shí)slot[0]=3。這兩個(gè)指令對(duì)應(yīng)源碼:x = 3 

iload_0  // 將局部變量表slot[0]的值(3)推入操作數(shù)棧,這是跟之前不一樣的地方,ireturn返回的值選擇的局部變量表不一樣 

ireturn 

從字節(jié)碼以及解釋來(lái)看,直接忽略了try語(yǔ)句塊中的return指令,這樣的代碼會(huì)讓人產(chǎn)生疑惑,所以平時(shí)不建議這么寫(xiě)。本章節(jié)就到這里了。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产精品日韩一区二区 | 色站综合 | 国产精品美女在线观看 | 亚洲三级在线观看 | 毛片黄视频 | 国产亚洲欧美一区二区 | 在线观看免费黄视频 | 精品一区二区电影 | 欧美在线资源 | 韩国精品一区二区 | 日韩激情在线 | 自拍偷拍一区 | 中文字幕在线观看第一页 | 一区二区三区在线免费观看 | 精品专区 | 中文字幕高清 | 国产成人综合一区 | 黄色影视网址 | 亚洲免费视频网 | 欧美亚洲国产日韩 | 欧美精品一区二区三区蜜桃视频 | 午夜视频在线观看网站 | 精品精品| 国产精品久久久久久久久图文区 | 国产精品精品久久久 | 中文字幕第18页 | 中文字幕啪啪 | 榴莲视频成人在线观看 | 精品国产青草久久久久福利 | 成人在线观看免费 | 国产日韩中文字幕 | 国产精品第一区 | 美女久久久久 | 精品久久久久久久久久久久久久 | 黄色av免费在线观看 | 欧美一级精品 | 人人澡人人透人人爽 | 国产欧美在线观看 | 一区二区三区高清 | 欧洲色视频 | 日韩精品视频在线播放 |