Java finally語(yǔ)句到底是在return之前還是之后執(zhí)行德召?

網(wǎng)上有很多人探討Java中異常捕獲機(jī)制try...catch...finally塊中的finally語(yǔ)句是不是一定會(huì)被執(zhí)行宇智?很多人都說不是,當(dāng)然他們的回答是正確的瑞筐,經(jīng)過我試驗(yàn)凄鼻,至少有兩種情況下finally語(yǔ)句是不會(huì)被執(zhí)行的:

  • try語(yǔ)句沒有被執(zhí)行到,如在try語(yǔ)句之前就返回了聚假,這樣finally語(yǔ)句就不會(huì)執(zhí)行块蚌,這也說明了finally語(yǔ)句被執(zhí)行的必要而非充分條件是:相應(yīng)的try語(yǔ)句一定被執(zhí)行到。

  • 在try塊中有System.exit(0);這樣的語(yǔ)句膘格,System.exit(0);是終止Java虛擬機(jī)JVM的峭范,連JVM都停止了,所有都結(jié)束了瘪贱,當(dāng)然finally語(yǔ)句也不會(huì)被執(zhí)行到纱控。

當(dāng)然還有很多人探討Finally語(yǔ)句的執(zhí)行與return的關(guān)系,頗為讓人迷惑菜秦,不知道finally語(yǔ)句是在try的return之前執(zhí)行還是之后執(zhí)行甜害?我也是一頭霧水,我覺得他們的說法都不正確球昨,我覺得應(yīng)該是:finally語(yǔ)句是在try的return語(yǔ)句執(zhí)行之后尔店,return返回之前執(zhí)行。這樣的說法有點(diǎn)矛盾主慰,也許是我表述不太清楚嚣州,下面我給出自己試驗(yàn)的一些結(jié)果和示例進(jìn)行佐證,有什么問題歡迎大家提出來共螺。

1. finally語(yǔ)句在return語(yǔ)句執(zhí)行之后return返回之前執(zhí)行的该肴。

public class FinallyTest1 {

    public static void main(String[] args) {
        
        System.out.println(test1());
    }

    public static int test1() {
        int b = 20;

        try {
            System.out.println("try block");

            return b += 80; 
        }
        catch (Exception e) {

            System.out.println("catch block");
        }
        finally {
            
            System.out.println("finally block");
            
            if (b > 25) {
                System.out.println("b>25, b = " + b);
            }
        }
        
        return b;
    }
    
}

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

try block
finally block
b>25, b = 100
100

說明return語(yǔ)句已經(jīng)執(zhí)行了再去執(zhí)行finally語(yǔ)句,不過并沒有直接返回璃谨,而是等f(wàn)inally語(yǔ)句執(zhí)行完了再返回結(jié)果沙庐。
如果覺得這個(gè)例子還不足以說明這個(gè)情況的話鲤妥,下面再加個(gè)例子加強(qiáng)證明結(jié)論:

public class FinallyTest1 {

    public static void main(String[] args) {
        
        System.out.println(test11());
    }
    
    public static String test11() {
        try {
            System.out.println("try block");

           return test12();
      } finally {
           System.out.println("finally block");
       }
  }

  public static String test12() {
       System.out.println("return statement");

       return "after return";
   }
    
}

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

try block
return statement
finally block
after return

說明try中的return語(yǔ)句先執(zhí)行了但并沒有立即返回,等到finally執(zhí)行結(jié)束后再返回拱雏。
這里大家可能會(huì)想:如果finally里也有return語(yǔ)句棉安,那么是不是就直接返回了,try中的return就不能返回了铸抑?看下面贡耽。

2. finally塊中的return語(yǔ)句會(huì)覆蓋try塊中的return返回。

public class FinallyTest2 {

    public static void main(String[] args) {

        System.out.println(test2());
    }

    public static int test2() {
        int b = 20;

        try {
            System.out.println("try block");

            return b += 80;
        } catch (Exception e) {

            System.out.println("catch block");
        } finally {

            System.out.println("finally block");

            if (b > 25) {
                System.out.println("b>25, b = " + b);
            }

            return 200;
        }

        // return b;
    }
}

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

try block
finally block
b>25, b = 100
200

這說明finally里的return直接返回了鹊汛,就不管try中是否還有返回語(yǔ)句蒲赂,這里還有個(gè)小細(xì)節(jié)需要注意,finally里加上return過后刁憋,finally外面的return b就變成不可到達(dá)語(yǔ)句了滥嘴,也就是永遠(yuǎn)不能被執(zhí)行到,所以需要注釋掉否則編譯器報(bào)錯(cuò)至耻。
這里大家可能又想:如果finally里沒有return語(yǔ)句若皱,但修改了b的值,那么try中return返回的是修改后的值還是原值尘颓?看下面走触。

3. 如果finally語(yǔ)句中沒有return語(yǔ)句覆蓋返回值,那么原來的返回值可能因?yàn)閒inally里的修改而改變也可能不變疤苹。

測(cè)試用例1:

public class FinallyTest3 {

    public static void main(String[] args) {
        System.out.println(test3());
    }
    public static int test3() {
        int b = 20;
        try {
            System.out.println("try block");
            return b += 80;
        } catch (Exception e) {
            System.out.println("catch block");
        } finally {
            System.out.println("finally block");
            if (b > 25) {
                System.out.println("b>25, b = " + b);
            }
            b = 150;
        }
        return 2000;
    }
}

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

try block
finally block
b>25, b = 100
100

測(cè)試用例2:

import java.util.*;

public class FinallyTest6
{
    public static void main(String[] args) {
        System.out.println(getMap().get("KEY").toString());
    }
     
    public static Map<String, String> getMap() {
        Map<String, String> map = new HashMap<String, String>();
        map.put("KEY", "INIT");
         
        try {
            map.put("KEY", "TRY");
            return map;
        }
        catch (Exception e) {
            map.put("KEY", "CATCH");
        }
        finally {
            map.put("KEY", "FINALLY");
            map = null;
        }
        return map;
    }
}

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

FINALLY

為什么測(cè)試用例1中finally里的b = 150;并沒有起到作用而測(cè)試用例2中finally的map.put("KEY", "FINALLY");起了作用而map = null;卻沒起作用呢互广?這就是Java到底是傳值還是傳址的問題了,具體請(qǐng)看精選30道Java筆試題解答卧土,里面有詳細(xì)的解答惫皱,簡(jiǎn)單來說就是:Java中只有傳值沒有傳址,這也是為什么map = null這句不起作用夸溶。這同時(shí)也說明了返回語(yǔ)句是try中的return語(yǔ)句而不是 finally外面的return b;這句逸吵,不相信的話可以試下凶硅,將return b;改為return 294缝裁,對(duì)原來的結(jié)果沒有一點(diǎn)影響。
這里大家可能又要想:是不是每次返回的一定是try中的return語(yǔ)句呢足绅?那么finally外的return b不是一點(diǎn)作用沒嗎捷绑?請(qǐng)看下面。

4. try塊里的return語(yǔ)句在異常的情況下不會(huì)被執(zhí)行氢妈,這樣具體返回哪個(gè)看情況粹污。

public class FinallyTest4 {

    public static void main(String[] args) {
        System.out.println(test4());
    }
    public static int test4() {
        int b = 20;
        try {
            System.out.println("try block");
            b = b / 0;
            return b += 80;
        } catch (Exception e) {
            b += 15;
            System.out.println("catch block");
        } finally {
            System.out.println("finally block");
            if (b > 25) {
                System.out.println("b>25, b = " + b);
            }
            b += 50;
        }
        return 204;
    }
}

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

try block
catch block
finally block
b>25, b = 35
85

這里因 為在return之前發(fā)生了除0異常,所以try中的return不會(huì)被執(zhí)行到首量,而是接著執(zhí)行捕獲異常的catch 語(yǔ)句和最終的finally語(yǔ)句壮吩,此時(shí)兩者對(duì)b的修改都影響了最終的返回值进苍,這時(shí)return b;就起到作用了。當(dāng)然如果你這里將return b改為return 300什么的鸭叙,最后返回的就是300觉啊,這毋庸置疑。
這里大家可能又有疑問:如果catch中有return語(yǔ)句呢沈贝?當(dāng)然只有在異常的情況下才有可能會(huì)執(zhí)行杠人,那么是在finally之前就返回嗎?看下面宋下。

5. 當(dāng)發(fā)生異常后嗡善,catch中的return執(zhí)行情況與未發(fā)生異常時(shí)try中return的執(zhí)行情況完全一樣。

public class FinallyTest5 {

    public static void main(String[] args) {
        System.out.println(test5());
    }

    public static int test5() {
        int b = 20;
        try {
            System.out.println("try block");    
            b = b /0;
            return b += 80;
        } catch (Exception e) {
            System.out.println("catch block");
            return b += 15;
        } finally {
            System.out.println("finally block");
            if (b > 25) {
                System.out.println("b>25, b = " + b);
            }
            b += 50;
        }
        //return b;
    }
}

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

try block
catch block
finally block
b>25, b = 35
35

說明了發(fā)生異常后学歧,catch中的return語(yǔ)句先執(zhí)行罩引,確定了返回值后再去執(zhí)行finally塊,執(zhí)行完了catch再返回枝笨,finally里對(duì)b的改變對(duì)返回值無(wú)影響蜒程,原因同前面一樣,也就是說情況與try中的return語(yǔ)句執(zhí)行完全一樣伺帘。

最后總結(jié):finally塊的語(yǔ)句在try或catch中的return語(yǔ)句執(zhí)行之后返回之前執(zhí)行且finally里的修改語(yǔ)句可能影響也可能不影響try或catch中 return已經(jīng)確定的返回值昭躺,若finally里也有return語(yǔ)句則覆蓋try或catch中的return語(yǔ)句直接返回。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末伪嫁,一起剝皮案震驚了整個(gè)濱河市领炫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌张咳,老刑警劉巖帝洪,帶你破解...
    沈念sama閱讀 222,865評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異脚猾,居然都是意外死亡葱峡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,296評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門龙助,熙熙樓的掌柜王于貴愁眉苦臉地迎上來砰奕,“玉大人,你說我怎么就攤上這事提鸟【” “怎么了?”我有些...
    開封第一講書人閱讀 169,631評(píng)論 0 364
  • 文/不壞的土叔 我叫張陵称勋,是天一觀的道長(zhǎng)胸哥。 經(jīng)常有香客問我,道長(zhǎng)赡鲜,這世上最難降的妖魔是什么空厌? 我笑而不...
    開封第一講書人閱讀 60,199評(píng)論 1 300
  • 正文 為了忘掉前任庐船,我火速辦了婚禮,結(jié)果婚禮上嘲更,老公的妹妹穿的比我還像新娘醉鳖。我一直安慰自己,他們只是感情好哮内,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,196評(píng)論 6 398
  • 文/花漫 我一把揭開白布盗棵。 她就那樣靜靜地躺著,像睡著了一般北发。 火紅的嫁衣襯著肌膚如雪纹因。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,793評(píng)論 1 314
  • 那天琳拨,我揣著相機(jī)與錄音瞭恰,去河邊找鬼。 笑死狱庇,一個(gè)胖子當(dāng)著我的面吹牛惊畏,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播密任,決...
    沈念sama閱讀 41,221評(píng)論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼颜启,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了浪讳?” 一聲冷哼從身側(cè)響起缰盏,我...
    開封第一講書人閱讀 40,174評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎淹遵,沒想到半個(gè)月后口猜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,699評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡透揣,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,770評(píng)論 3 343
  • 正文 我和宋清朗相戀三年济炎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片辐真。...
    茶點(diǎn)故事閱讀 40,918評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡须尚,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出拆祈,到底是詐尸還是另有隱情恨闪,我是刑警寧澤倘感,帶...
    沈念sama閱讀 36,573評(píng)論 5 351
  • 正文 年R本政府宣布放坏,位于F島的核電站,受9級(jí)特大地震影響老玛,放射性物質(zhì)發(fā)生泄漏淤年。R本人自食惡果不足惜钧敞,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,255評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望麸粮。 院中可真熱鬧溉苛,春花似錦、人聲如沸弄诲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,749評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)齐遵。三九已至寂玲,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間梗摇,已是汗流浹背拓哟。 一陣腳步聲響...
    開封第一講書人閱讀 33,862評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留伶授,地道東北人断序。 一個(gè)月前我還...
    沈念sama閱讀 49,364評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像糜烹,于是被迫代替她去往敵國(guó)和親违诗。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,926評(píng)論 2 361

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

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法疮蹦,類相關(guān)的語(yǔ)法较雕,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法挚币,異常的語(yǔ)法亮蒋,線程的語(yǔ)...
    子非魚_t_閱讀 31,668評(píng)論 18 399
  • 昨晚想了一夜,昨天的兩個(gè)交易都是失敗的交易妆毕,還是原來的思維和行為習(xí)慣慎玖,下跌了繼續(xù)補(bǔ)倉(cāng),結(jié)果損失越來越大笛粘,上漲...
    我的真諦閱讀 277評(píng)論 0 0
  • 認(rèn)知是別人不知道的觀點(diǎn)趁怔,視野是別人不知道的事實(shí)。
    余子祥閱讀 140評(píng)論 0 1
  • 石灰粉閱讀 637評(píng)論 1 9
  • 算了,跳廣場(chǎng)舞去 文/胡大小姐 做家務(wù)在我心里大概是洪水猛獸般的存在示括。 小時(shí)候铺浇,我媽天天都要洗衣做飯,尤其是家里的...
    41813ed69537閱讀 245評(píng)論 0 1