国产成人精品18p,天天干成人网,无码专区狠狠躁天天躁,美女脱精光隐私扒开免费观看

Java中return和finally哪個(gè)先執行

發(fā)布時(shí)間:2021-07-03 23:03 來(lái)源:億速云 閱讀:0 作者:Leah 欄目: 開(kāi)發(fā)技術(shù)

這期內容當中小編將會(huì )給大家帶來(lái)有關(guān)Java中return和finally哪個(gè)先執行,文章內容豐富且以專(zhuān)業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

源碼:

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)單地得出結論:return在finally之前執行,我們來(lái)看下字節碼層面上發(fā)生了什么事情。下面截取case1方法的部分字節碼,并且對照源碼,將每個(gè)指令的含義注釋在后面:

iconst_1 // 將常量1推入操作數棧頂  istore_0 // 彈出棧頂元素(1),保存到局部變量表slot[0],此時(shí)slot[0]=1。這兩條指令對應源碼:x = 1;  iload_0 // 將局部變量表slot[0]的值推入操作數棧頂,也就是說(shuō)把上面x的值推入棧頂  istore_1 // 彈出棧頂元素(1),保存到局部變量表slot[1],此時(shí)slot[1]=1。其實(shí),此時(shí)就已經(jīng)把要return的值準備好了  iconst_3 // 將常量3推入操作數棧頂,這一條指令開(kāi)始,其實(shí)是開(kāi)始執行finally中的代碼了  istore_0 // 彈出棧頂元素(3),保存到局部變量表slot[0],此時(shí)slot[0]=3。這兩個(gè)指令對應源碼:x = 3;這里要注意的是,雖然都是更新了x的值,但是finally中的x和try中x的賦值,保存在了不同的局部變量表中 iload_1 // 將局部變量表slot[1]的值推入操作數棧頂,此時(shí)棧頂元素的值為1,是第3行指令保存的值  ireturn // 將操作數棧頂的值返回給調用方

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

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

public static int case2() {     int x;     try {         x = 1;         return ++x;     } finally {         x = 3;     } }  # 輸出

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

iconst_1 // 將常量1推入操作數棧頂 istore_0 // 彈出棧頂元素(1),保存到局部變量表slot[0],此時(shí)slot[0]=1。這兩條指令對應源碼:x = 1; iinc          0, 1 // 對局部變量表slot[0]進(jìn)行自增(+1)操作,此時(shí)slot[0]=2,對應源碼:++x;所以,可以看出return后面的表達式先執行 iload_0 // 將局部變量表slot[0]的值推入操作數棧頂,也就是說(shuō)把上面x的值(2)推入棧頂 istore_1 // 彈出棧頂元素(2),保存到局部變量表slot[1],此時(shí)slot[1]=2。其實(shí),此時(shí)就已經(jīng)把要return的值準備好了 iconst_3 // 將常量3推入操作數棧頂,這一條指令開(kāi)始,其實(shí)是開(kāi)始執行finally中的代碼了 istore_0 // 彈出棧頂元素(3),保存到局部變量表slot[0],此時(shí)slot[0]=3。這兩個(gè)指令對應源碼:x = 3;這里要注意的是,雖然都是更新了x的值,但是finally中的x和try中x的賦值,保存在了不同的局部變量表中 iload_1 // 將局部變量表slot[1]的值推入操作數棧頂,此時(shí)棧頂元素的值為2,是第6行指令保存的值,也就是經(jīng)過(guò)++x之后的值 ireturn // 將操作數棧頂的值返回給調用方

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

總結一下,return指令是最后執行的,如果return后面有表達式,則執行完表達式之后就執行finally中的語(yǔ)句,最后再執行return指令。所以說(shuō)finally和return到底哪個(gè)先執行:return指令后面如果有表達式或方法調用的話(huà),先執行,然后執行finally,最后執行return指令。就像上面的程序演示的結果,不能光從x的賦值來(lái)看最終返回結果,從指令層面看,兩次對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返回結果的示例,平時(shí)不建議這么寫(xiě),我們同樣從字節碼的角度來(lái)分析下:

iconst_1 // 將常量1推入操作數棧頂 istore_0 // 彈出棧頂元素(1),保存到局部變量表slot[0],此時(shí)slot[0]=1。這兩條指令對應源碼:x = 1; iinc          0, 1 // 對局部變量表slot[0]進(jìn)行自增(+1)操作,此時(shí)slot[0]=2,對應源碼:++x;所以,可以看出return后面的表達式先執行 iload_0  // 將局部變量表slot[0]的值推入操作數棧頂,也就是說(shuō)把上面x的值(2)推入棧頂 istore_1 // 彈出棧頂元素(2),保存到局部變量表slot[1],此時(shí)slot[1]=2。 iconst_3 // 將常量3推入操作數棧頂,這一條指令開(kāi)始,其實(shí)是開(kāi)始執行finally中的代碼了 istore_0 // 彈出棧頂元素(3),保存到變量表slot[0],此時(shí)slot[0]=3。這兩個(gè)指令對應源碼:x = 3 iload_0  // 將局部變量表slot[0]的值(3)推入操作數棧,這是跟之前不一樣的地方,ireturn返回的值選擇的局部變量表不一樣 ireturn

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

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自互聯(lián)網(wǎng)轉載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權請聯(lián)系QQ:712375056 進(jìn)行舉報,并提供相關(guān)證據,一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容。

男女超爽视频免费播放| GOGOGO高清在线播放免费| 老熟妇乱子伦牲交视频| 日韩一线无码AV毛片免费| 亚洲AV鲁丝一区二区三区黄| 久久精品午夜福利|