面試題思考:try 代碼塊中含 return 語句時图筹,代碼執(zhí)行順序

刷java面試題偶然看到這類問題(try/finally中含有return時的執(zhí)行順序)远剩,覺得挺有意思于是小小的研究了一下骇窍,希望經(jīng)過我添油加醋天馬行空之后,能給你帶來一定的幫助

原題

try {} 里有一個return語句痢掠,那么緊跟在這個try后的finally {}里的代碼會不會被執(zhí)行?什么時候被執(zhí)行?在return前還是后?

乍一看題目很簡單嘛嘲恍,java規(guī)范都說了,finally會在try代碼塊的return之前執(zhí)行姑廉,你這文章寫得沒意義涯保,不看了

你等等逃片!(拿起我身邊的五尺砍刀)

神奇栗子

看完這個栗子攻冷,你在想想執(zhí)行順序到底是怎樣的

栗子代碼

    public static void main(String[] args) {
        int result = test();
        System.out.println(result);
    }

    public static int test() {
        int t = 0;
        try {
            return t;
        } finally {
            ++t;
        }
    }

分析一下

test()方法內等曼,在try中return了t凿蒜,那么在main方法中test()函數(shù)的返回值應該是t=0,即控制臺輸出0

但是因為有finally的存在州泊,而finally中對t進行了自增運算漂洋,并且finally會在try中的return語句之前執(zhí)行,所以正確的情況是控制臺輸出1

所以你最終確定的答案是:控制臺輸出1

然而事實并非如此演训,將程序跑起來之后样悟,得到的結果是:
輸出0
將栗子跑起來親眼看一下吧~

得到這個結果你也許要爆炸了庭猩,啥?java規(guī)范說的都是錯的礁苗?徙缴!

不用急,到我給sun洗地的時間了

洗地時間

在洗地之前疏叨,你很有必要先理解java中的值傳遞穿剖,如果你已經(jīng)了解該內容可略過下面這一個小節(jié)點

java中的值傳遞

由于這只是本文內容引申出去的知識點糊余,不過多贅述单寂,隨便嘮兩句吐辙,能借此明白則好昏苏,不明白希望借助搜索引擎明白一下!

在java的方法調用中贤惯,時常需要傳遞參數(shù)孵构,那么傳遞的參數(shù)是將之前的變量直接傳遞給方法內了嗎?

顯然不是的棒假,調用方法傳遞參數(shù)的時候精盅,傳遞的只是原變量的一個副本(復制體),換句話說就是妻枕,將變量的值傳遞給了方法體粘驰,而并沒有真正的將變量傳遞進去蝌数。

看個栗子:

    public static void main(String[] args) {
        int t = 0;
        test(t);
        System.out.println(t);
    }

    public static int test(int a) {
        a = 111;
    }

正確輸出是0,因為test()方法內拿到的a饵撑,只是t的一個副本(復制體)而并不直接是t唆貌,test()內改變了a的值,并不影響t的值

以上是對于基本數(shù)據(jù)類型语卤,如果對于對象呢粹舵?

如果參數(shù)是對象,那么傳遞的是對象的引用副本(復制體)齐婴,這也就是為什么在方法體內對對象進行修改柠偶,會真正的改變對象睬关。因為方法體外的引用和方法體內的引用指向的是堆內存中的同一個對象,傳遞的是對象的引用

如果這里還不能理解值傳遞蔫仙,建議先理解一下這一個概念再繼續(xù)往下看

真的開始分析了

為了你看著方便丐箩,栗子代碼再來一份:(我真的不是為了湊字數(shù))

    public static void main(String[] args) {
        int result = test();
        System.out.println(result);
    }

    public static int test() {
        int t = 0;
        try {
            return t;
        } finally {
            ++t;
        }
    }
  1. 當代碼執(zhí)行到return t;時屎勘,并不是直接將t返回了出去,而是將t保留了起來(因為還有一個finally語句塊沒有執(zhí)行!)
    并且這個保留丑慎,就是值傳遞性質的一個保留竿裂,也就是保留的是t的一個副本(復制體)照弥,我這里先叫他tt吧(不是套套!这揣!)
  1. 接下來執(zhí)行finally語句塊曾沈,finally中將t做了自增運算,t的確變成了1姐帚,但是這并沒有影響t的復制體tt的值障涯!保留起來的tt值還是0!
  2. 這個時候執(zhí)行完了finally九秀,正式將保留起來的tt返回出去鼓蜒,于是,整個函數(shù)的返回結果就是0
  3. 這個t的副本(復制體)保留的地方是哪兒呢娇豫?我查了半天畅厢,有個應該靠譜的說法冯痢,保留在函數(shù)棧中,但具體保留的區(qū)域叫什么框杜,我也不知道浦楣,還請知情大佬指教一下!

上圖或許直觀一點咪辱?

靈魂畫師
靈魂畫師

叫我一聲靈魂畫師我可敢答應振劳!

那么如果,這個t是一個對象呢梧乘?按照前面說的值傳遞的問題澎迎,如果t是一個對象,在finally中對t進行修改选调,那么最終返回出去的t所顯示出來的數(shù)據(jù),應該是經(jīng)過修改的仁堪。

寫一個Person類來檢驗一下吧

public class Test {

    public static void main(String[] args) {
        Person result = test();
        System.out.println(result.age);
    }

    public static Person test() {
        Person t = new Person();
        t.age = 0;
        try {
            return t;
        } finally {
            t.age++;
            
        }
    }

}

class Person {
    int age;
}

這段代碼輸出的是1哮洽,因為Person是一個類,t是一個對象的引用弦聂,對象實例保存在堆內存中鸟辅,t的副本tt也是一個對象的引用,t和tt都指向堆內存中的對象實例莺葫,那么不論修改誰匪凉,實際上對象實例都被修改了!

看完我這一通胡說八道捺檬,你應該了解了整個執(zhí)行流程咯再层?

那么繼續(xù)開一個引申

又一個小栗子

如果在finally中也有一個return,會發(fā)生什么?

    public static void main(String[] args) {
        int result = test();
        System.out.println(result);
    }

    public static int test() {
        int t = 0;
        try {
            return t;
        } finally {
            ++t;
            return t;
        }
    }

最終輸出的結果是1

就是說聂受,如果try中有return而finally中也有return蒿秦,那么后者將會讓前者失效!

理解

=> try中將t保留了一份副本用于返回出去蛋济,到了finally中棍鳖,又有一個return語句,這時候又要創(chuàng)建一個用于返回的副本碗旅,那這個時候就有兩個副本了渡处,到底返回誰呢?取后者扛芽!

總結

這一個面試題骂蓖,看似簡單积瞒,卻暗藏殺機按狻!

可是說了這么多茫孔,結果就是finally在return之后執(zhí)行嗎叮喳?

非也,你沒看見return沒有真正的執(zhí)行完就開始執(zhí)行finally嗎缰贝?并且是先執(zhí)行完了finally馍悟,才執(zhí)行完return,這也就很好理解java規(guī)范中的finally在return之前執(zhí)行了剩晴。

不過锣咒,按如上情況,這句話應該變成這樣:finally比return先執(zhí)行完畢赞弥。是不是就更容易理解了呢毅整?
也就是說,return先被執(zhí)行了绽左,執(zhí)行return的時候發(fā)現(xiàn)有finally悼嫉,于是不能那么快執(zhí)行完畢return,先去執(zhí)行finally拼窥,等finally執(zhí)行完畢之后戏蔑,return才能執(zhí)行完畢。

全文下來鲁纠,真是用我的三寸不爛之舌經(jīng)過滔滔不絕的輸出連綿不絕的蠱惑打開了你的新世界大門啊

結語

更多內容歡迎訪問我的主頁我的博客
如果我的文章確實有幫助到你总棵,請不要忘了點一下文末的"?"讓他變成"?"
作為一直雛雞難免很多地方理解不到位,文中若有錯誤請直(bu)接(yao)指(ma)出(wo)
寫作不易改含!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末情龄,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌刃唤,老刑警劉巖隔心,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異尚胞,居然都是意外死亡硬霍,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進店門笼裳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來唯卖,“玉大人,你說我怎么就攤上這事躬柬“莨欤” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵允青,是天一觀的道長橄碾。 經(jīng)常有香客問我,道長颠锉,這世上最難降的妖魔是什么法牲? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮琼掠,結果婚禮上拒垃,老公的妹妹穿的比我還像新娘。我一直安慰自己瓷蛙,他們只是感情好悼瓮,可當我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著艰猬,像睡著了一般横堡。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上姥宝,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天翅萤,我揣著相機與錄音,去河邊找鬼腊满。 笑死套么,一個胖子當著我的面吹牛,可吹牛的內容都是我干的碳蛋。 我是一名探鬼主播胚泌,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼肃弟!你這毒婦竟也來了玷室?” 一聲冷哼從身側響起零蓉,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎穷缤,沒想到半個月后敌蜂,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡津肛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年章喉,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片身坐。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡秸脱,死狀恐怖,靈堂內的尸體忽然破棺而出部蛇,到底是詐尸還是另有隱情摊唇,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布涯鲁,位于F島的核電站巷查,受9級特大地震影響,放射性物質發(fā)生泄漏撮竿。R本人自食惡果不足惜吮便,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一笔呀、第九天 我趴在偏房一處隱蔽的房頂上張望幢踏。 院中可真熱鬧,春花似錦许师、人聲如沸房蝉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽搭幻。三九已至,卻和暖如春逞盆,著一層夾襖步出監(jiān)牢的瞬間檀蹋,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工云芦, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留俯逾,地道東北人。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓舅逸,卻偏偏與公主長得像桌肴,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子琉历,可洞房花燭夜當晚...
    茶點故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內容

  • 1. Java基礎部分 基礎部分的順序:基本語法坠七,類相關的語法水醋,內部類的語法,繼承相關的語法彪置,異常的語法拄踪,線程的語...
    子非魚_t_閱讀 31,581評論 18 399
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn)拳魁,斷路器宫蛆,智...
    卡卡羅2017閱讀 134,599評論 18 139
  • 小編費力收集:給你想要的面試集合 1.C++或Java中的異常處理機制的簡單原理和應用。 當JAVA程序違反了JA...
    八爺君閱讀 4,573評論 1 114
  • (一)Java部分 1的猛、列舉出JAVA中6個比較常用的包【天威誠信面試題】 【參考答案】 java.lang;ja...
    獨云閱讀 7,071評論 0 62
  • 本文參加#感悟三下鄉(xiāng)耀盗,青春筑夢行#活動,本人承諾卦尊,文章內容為原創(chuàng)叛拷,且未在其他平臺發(fā)表過。 我們是安徽師范大學生命科...
    oh窗外閱讀 210評論 0 0