亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

你真的了解try{ return }finally{}中的return?

2019-11-14 23:33:20
字體:
來源:轉載
供稿:網友
你真的了解try{ return }finally{}中的return?

今天去逛論壇 時發現了一個很有趣的問題:

誰能給我我解釋一下這段程序的結果為什么是:2.而不是:3

代碼如下:

class Test {public int aaa() {int x = 1;try {return ++x;} catch (Exception e) {} finally {++x;}return x;}public static void main(String[] args) {Test t = new Test();int y = t.aaa();System.out.PRintln(y);}}

看了問題后,得出了以下幾個問題:

  • 如果在 try 語句塊里使用 return 語句,那么 finally 語句塊還會執行嗎?(果你的答案是不會執行,請務必要看下去 ^_^)
  • 如果執行,那么是怎樣實現既執行 return 又執行 finally 的呢?(如果你的答案是不知道,請繼續看下去?。。?/li>
  • 上面的程序輸出為什么是2?( 如果不知道,繼續看下去~~)
  • 在網上看到還有人還問“是先執行return還是先執行finally?”的 (個人覺得,如果知道finally會執行就可以得出是,先執行finally再執行return的。因為,如果先執行return,那么整個函數都跳出了,那么還怎么執行finally?^_^)

剛看到這個問題后。突然發現基礎不夠扎實,居然來第一個都答不出來。。。(不知道還有木有和我也一樣也回答不出以上的問題的? 如果有請在評論里告訴我一聲,讓我知道,我并不孤獨~~)

根據已有的知識知道:return 是可以當作終止語句來用的,我們經常用它來跳出當前方法,并返回一個值給調用方法。然后該方法就結束了,不會執行return下面的語句。finally :無論try語句發生了什么,無論拋出異常還是正常執行。finally語句都會執行。那么問題來了。。。。在try語句里使用return后,finally是否還會執行?finally一定會執行的說法是否還成立?如果成立,那么先執行return還是先執行finally?

驗證 finally 語句是否會執行,以及 return 和 finally的執行順序

在求知欲的驅動下,我繼續進行更深的探索,果斷打開了Oracle的主頁,翻閱了java 官方教程的finally語句。發現了官方教程對這個特殊情況有說明:

The finally block always executes when the try block exits. This ensures that the finally block is executed even if an unexpected exception occurs. But finally is useful for more than just exception handling — it allows the programmer to avoid having cleanup code accidentally bypassed by a return, continue, or break. Putting cleanup code in a finally block is always a good practice, even when no exceptions are anticipated.

Note: If the JVM exits while the try or catch code is being executed, then the finally block may not execute. Likewise, if the thread executing the try or catch code is interrupted or killed, the finally block may not execute even though the application as a whole continues.

個人簡單翻譯

當try語句退出時肯定會執行finally語句。這確保了即使發了一個意想不到的異常也會執行finally語句塊。但是finally的用處不僅是用來處理異?!梢宰尦绦騿T不會因為return、continue、或者break語句而忽略了清理代碼。把清理代碼放在finally語句塊里是一個很好的做法,即便可能不會有異常發生也要這樣做。

注意,當try或者catch的代碼在運行的時候,JVM退出了。那么finally語句塊就不會執行。同樣,如果線程在運行try或者catch的代碼時被中斷了或者被殺死了(killed),那么finally語句可能也不會執行了,即使整個運用還會繼續執行。

從上面的官方說明,我們知道無論try里執行了return語句、break語句、還是continue語句,finally語句塊還會繼續執行。同時,在stackoverflow里也找到了一個答案,我們可以調用System.exit()來終止它:

finally will be called.The only time finally won't be called is: if you call System.exit(), another thread interrupts current one, or if the JVM crashes first.

另外,在java的語言規范有講到,如果在try語句里有return語句,finally語句還是會執行。它會在把控制權轉移到該方法的調用者或者構造器前執行finally語句。也就是說,使用return語句把控制權轉移給其他的方法前會執行finally語句。

個人驗證

我們依然使用上面的代碼作為例子。首先,分別在以下三行代碼前加上斷點:

  • int x = 1;
  • return ++x;
  • ++x;

然后以debug模式運行代碼。

剛開始時,效果如下圖:

按一下F6,我們可以發現,程序已經執行到 return ++x;,但還沒執行該語句,此刻x=1

繼續按一下F6,程序執行到 ++x;,但還沒執行該語句,因此此時的x=2(剛執行完return ++x語句的++x,但沒執行return)

繼續按一下F6,此時,我們發現程序又跳回到 return +xx 這一行,此刻x=3(執行了finally語句里的++x)

從上面過程中可以看到,

  • try 里 使用 return 還是會執行finally語句的(我們用debug的模式看到了程序會條件 finally語句里執行)
  • 執行完finally語句才執行 return。為什么?從上面的圖可以合理推理出return +xx;是分開來執行的,先執行++x,再執行finally,最后才執行return跳出函數。因為程序調兩次跳到了 return +xx; 語句上。(其實要驗證 return ++x 是分開兩部分執行的方法很簡單,把變量x變成static變量并在main函數里輸出,會發現x的值還是3,即使兩次跳到 return ++x 也只是第一次執行了加1操作,第二次只是執行了return而沒有執行++x。這里是合理推理,后面有真憑實據~~)

看到這,我們可能會再次糾結起來了。從上面的驗證可以看出,finally語句執行了,而且x的值也確實加到3了,那么為什么y是2呢?

驗證為什么是2不是3

翻看官方的jvm規范就會把一切的謎團解開了:

If the try clause executes a return, the compiled code does the following:

  1. Saves the return value (if any) in a local variable.
  2. Executes a jsr to the code for the finally clause.
  3. Upon return from the finally clause, returns the value saved in the local variable.

簡單翻譯下:

如果try語句里有return,那么代碼的行為如下:1.如果有返回值,就把返回值保存到局部變量中2.執行jsr指令跳到finally語句里執行3.執行完finally語句后,返回之前保存在局部變量表里的值

根據上面的說明就可以輕易地解釋為什么是2了。當執行到return ++x;時,jvm在執行完++x后會在局部變量表里另外分配一個空間來保存當前x的值。注意,現在還沒把值返回給y,而是繼續執行finally語句里的語句。等執行完后再把之前保存的值(是2不是x)返回給y。所以就有了y是2不是3的情況。

其實這里還有一點要注意的是,如果你在finally里也用了return語句,比如return +xx。那么y會是3。因為規范規定了,當try和finally里都有return時,會忽略try的return,而使用finally的return。

查看Test.class的字節碼我們同樣也可以很輕松地知道為什么是2而不是3:

大概講講指令操作順序:iconst_1: 把常數1進棧 ---> istore_1: 棧頂元素出棧并把元素保存在本地變量表的第二個位置里(下標為1的位置里) ---> iinc 1, 1 : 本地變量表的第二個元素自增1 --->iload_1:第二個元素進棧 ---> istore_2:棧頂元素出棧并把元素保存在本地變量表的第2個位置里 ---> iinc 1, 1 : 本地變量表的第二個元素自增1 ---> iload_2:第二個元素進棧 (注意,此時棧頂元素為2)---> ireturn:返回棧頂元素。

后面的指令是要在2-7行出現異常時在跳到12行的,這個例子沒出現異常,不用關注。

上面流程棧和本地變量表的情況如下圖:

總結
  • 再次發現幫助別人解決問題的好處,不僅能幫人還能完善自己
  • 字節碼的知識還是挺實用的,有空要深入研究下
  • 再次證明官方教程和資料真的很有用

參考資料:Java虛擬機規范java 官方教程的finally語句IBM的Java字節碼教程深入理解Java虛擬機(第2版)


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久久人成影片一区二区三区| 日韩视频免费大全中文字幕| 欧美黄色小视频| 欧美激情aaaa| 91在线视频免费| 夜夜嗨av一区二区三区免费区| 97视频在线观看免费| 国模视频一区二区三区| 亲子乱一区二区三区电影| 亚洲精选在线观看| 欧美一区二区三区免费视| 欧美日韩午夜激情| 青草青草久热精品视频在线观看| 国产成人免费av电影| 精品久久久久久久久久ntr影视| 久久久久久网站| 久久久久国产一区二区三区| 黄色成人av网| 精品视频—区二区三区免费| 亚洲va码欧洲m码| 日韩欧美在线字幕| 精品国产成人在线| 最近免费中文字幕视频2019| 亚洲片在线资源| 亚洲美腿欧美激情另类| 欧美成人在线免费视频| 国产精品v日韩精品| 欧美性xxxx18| 亚洲色图17p| 亚洲欧美日韩爽爽影院| 日韩一级黄色av| 91精品视频在线看| 国产一区二区三区免费视频| 亚洲国产精品专区久久| 欧美又大又硬又粗bbbbb| 丝袜一区二区三区| 亚洲人在线视频| 久久综合国产精品台湾中文娱乐网| 午夜精品一区二区三区在线视| 久久人人爽人人爽人人片av高清| 亚洲自拍偷拍在线| 97视频免费观看| 亚洲国模精品私拍| 久久精品国产一区二区三区| 蜜臀久久99精品久久久无需会员| 4k岛国日韩精品**专区| 在线播放亚洲激情| 欧美性黄网官网| 中文字幕精品久久久久| 亚洲国产精品美女| 精品国产一区二区三区久久狼黑人| 亚洲第一av在线| 午夜精品久久久久久久99热| 97色在线观看免费视频| 成人午夜一级二级三级| 欧美日韩成人在线播放| 中文字幕一区日韩电影| 国产精品视频999| 国产精品福利在线观看| 欧洲亚洲免费在线| 欧美午夜美女看片| 91九色蝌蚪国产| 国产精品美女呻吟| 粉嫩av一区二区三区免费野| 91久久中文字幕| 国产成人一区二区三区小说| 国产97在线观看| 97久久伊人激情网| 久久免费成人精品视频| 国产亚洲精品高潮| 欧美精品电影免费在线观看| 欧美视频专区一二在线观看| 久久久久北条麻妃免费看| 亚洲精品视频网上网址在线观看| 韩国一区二区电影| 亚洲91av视频| 欧美在线视频观看免费网站| 免费97视频在线精品国自产拍| 91在线无精精品一区二区| 91精品久久久久久久久久久| 欧美国产中文字幕| 成人性生交大片免费看视频直播| 久久精品中文字幕一区| 国产日韩中文在线| 国产精品一区二区三区成人| 亚洲精品视频在线观看视频| 国产精品欧美日韩一区二区| 欧美日韩免费观看中文| 欧美肥老太性生活视频| 亚洲人成电影网站色xx| yellow中文字幕久久| 亚洲999一在线观看www| 久久色免费在线视频| 色妞久久福利网| 精品欧美一区二区三区| 欧美大片在线看| 亚洲欧美中文字幕| 日本高清不卡的在线| 91在线视频免费| 欧美另类暴力丝袜| 精品成人在线视频| 91免费视频国产| 国产欧美精品久久久| 国产欧美久久久久久| 亚洲男人天堂2024| 久久久免费精品视频| 日本欧美黄网站| 奇米四色中文综合久久| 国产成人综合一区二区三区| 国产美女精彩久久| 另类少妇人与禽zozz0性伦| 91色视频在线观看| 国产成人涩涩涩视频在线观看| 亚洲精品成人网| 欧美成人sm免费视频| 91国产精品电影| 久久久久久久影院| 欧美成人久久久| 欧美成人精品三级在线观看| 全亚洲最色的网站在线观看| 国产精品稀缺呦系列在线| 欧美激情一二区| 97涩涩爰在线观看亚洲| 自拍偷拍亚洲在线| 成人黄色av免费在线观看| 色狠狠久久aa北条麻妃| 按摩亚洲人久久| 久久亚洲国产成人| 久久精品青青大伊人av| 亚洲人永久免费| 欧美日韩福利电影| 亚洲国产成人91精品| 国产欧美精品一区二区| 国产精品中文字幕久久久| 亚洲精品美女网站| 久久6免费高清热精品| 亚洲午夜精品久久久久久性色| 日韩欧美国产成人| 久久久999精品视频| 国产一区二区三区在线视频| 日韩成人黄色av| 亚洲精品www久久久| 成人看片人aa| 亚洲精品久久久久国产| 亚洲国产中文字幕久久网| 丝袜一区二区三区| 欧美中文字幕在线视频| 国产精品视频免费观看www| 欧美日韩国产精品| 精品国产福利在线| 日本韩国欧美精品大片卡二| 一级做a爰片久久毛片美女图片| 日韩成人在线播放| 一区二区亚洲精品国产| 中文字幕免费国产精品| 亚洲精品动漫100p| 日韩在线视频一区| 日韩av免费一区| 久久国产精品视频| 91久久精品国产| 热re99久久精品国产66热| 国产精欧美一区二区三区| 精品国产一区二区三区久久| 亚洲视屏在线播放|