Java中try-catch-finally執(zhí)行順序你知道嗎
引言
java異常處理中,try、catch、finally的執(zhí)行順序,大家都知道是按順序執(zhí)行的,這里我就不廢話了。但是當(dāng)try、catch、finally中加入return之后,就會(huì)有幾種不同的情況出現(xiàn),下面分別來說明一下。也可以跳到最后直接看總結(jié)。
正文
這里共列舉五種情況,會(huì)對(duì)其一一說明。
try塊中有return
try{ System.out.println("try塊代碼運(yùn)行了"); return 0; }catch(Exception e){ System.out.println("catch塊代碼運(yùn)行了"); }finally { System.out.println("finally塊代碼運(yùn)行了"); } return 1;
輸出結(jié)果:
try塊代碼運(yùn)行了
finally塊代碼運(yùn)行了
?
最終返回:0
執(zhí)行流程:
執(zhí)行try塊中return前(包括return語(yǔ)句中的表達(dá)式運(yùn)算)的代碼 -> 執(zhí)行finally塊 -> 執(zhí)行try中return。
結(jié)論:
當(dāng)try中帶有return時(shí),會(huì)先執(zhí)行return前的代碼,然后暫時(shí)保存需要return的信息,再執(zhí)行finally中的代碼,最后再通過return返回之前保存的信息。finally塊之后的語(yǔ)句return不再執(zhí)行,因?yàn)槌绦蛟趖ry中已經(jīng)return過了,方法的執(zhí)行已經(jīng)結(jié)束。
但有一點(diǎn)需要注意,如果返回值是引用類型呢?再看另外一個(gè)例子:
List<Integer> list = new ArrayList<>(); try { list.add(0); System.out.println("try:" + list); return list; } catch (Exception e) { list.add(1); System.out.println("catch:" + list); } finally { list.add(2); System.out.println("finally:" + list); } return list;
輸出:
try:[0]
finally:[0,2]
?
最終返回:[0,2]
看完這個(gè)例子,可能會(huì)發(fā)現(xiàn)問題,剛提到return時(shí)會(huì)臨時(shí)保存需要返回的信息,不受finally塊中代碼的影響。但是在這里,list里存的不是變量本身,而是變量的地址,所以當(dāng)finally通過地址改變了變量,還是會(huì)影響方法返回值的。
catch塊中有return
try{ System.out.println("try塊代碼運(yùn)行了"); //int x = 1 / 0 ; }catch(Exception e){ System.out.println("catch塊代碼運(yùn)行了"); return 0; }finally { System.out.println("finally塊代碼運(yùn)行了"); } return 1;
輸出結(jié)果:
//無(wú)異常
try塊代碼運(yùn)行了
finally塊代碼運(yùn)行了
最終返回:1
//有異常
try塊代碼運(yùn)行了
catch塊代碼運(yùn)行了
finally塊代碼運(yùn)行了
最終返回:0
執(zhí)行流程:
程序先執(zhí)行try,如果遇到異常執(zhí)行catch塊。
有異常:執(zhí)行catch中return之前(包括return語(yǔ)句中的表達(dá)式運(yùn)算)代碼,再執(zhí)行finally語(yǔ)句中全部代碼,最后執(zhí)行catch塊中return, finally之后的return不再執(zhí)行。
無(wú)異常:執(zhí)行完try再finally再return。
結(jié)論:
catch中return與try中類似,若出現(xiàn)異常,會(huì)暫時(shí)保存catch塊中return的信息,再執(zhí)行finally中的代碼,最后再通過return返回之前保存的信息。
try塊和finally塊中有return
try{ System.out.println("try塊代碼運(yùn)行了"); return 0; }catch(Exception e){ System.out.println("catch塊代碼運(yùn)行了"); ? }finally { System.out.println("finally塊代碼運(yùn)行了"); return 1; }
輸出結(jié)果:
try塊代碼運(yùn)行了
finally塊代碼運(yùn)行了
最終返回:1
執(zhí)行流程:
程序執(zhí)行try塊中return之前(包括return語(yǔ)句中的表達(dá)式運(yùn)算)代碼,再執(zhí)行finally塊。因?yàn)閒inally塊中有return所以提前退出,而不再執(zhí)行try中的return。
備注:
這種寫法是可以編譯通過的,但是編譯器會(huì)給予警告。我們一般不在finally塊中寫return語(yǔ)句,這里只是刻意演示了一下效果。
catch塊和finally塊中有return
try{ System.out.println("try塊代碼運(yùn)行了"); //int x = 1 / 0 ; }catch(Exception e){ System.out.println("catch塊代碼運(yùn)行了"); return 0; }finally { System.out.println("finally塊代碼運(yùn)行了"); return 1; }
輸出結(jié)果:
//無(wú)異常
try塊代碼運(yùn)行了
finally塊代碼運(yùn)行了
最終返回:1//有異常
try塊代碼運(yùn)行了
catch塊代碼運(yùn)行了
finally塊代碼運(yùn)行了
最終返回:1
執(zhí)行流程:
無(wú)異常:執(zhí)行try后跳過catch執(zhí)行finally,得到finally的返回值1;
有異常:程序執(zhí)行catch塊中return之前(包括return語(yǔ)句中的表達(dá)式運(yùn)算)代碼,再執(zhí)行finally塊。因?yàn)閒inally塊中有return所以提前退出,而不再執(zhí)行catch中的return。
try塊、catch塊和finally塊中都有return
try{ System.out.println("try塊代碼運(yùn)行了"); //int x = 1 / 0 ; return 0; }catch(Exception e){ System.out.println("catch塊代碼運(yùn)行了"); return 1; }finally { System.out.println("finally塊代碼運(yùn)行了"); return 2; }
輸出結(jié)果:
//無(wú)異常
try塊代碼運(yùn)行了
finally塊代碼運(yùn)行了最終返回:2
//有異常
try塊代碼運(yùn)行了
catch塊代碼運(yùn)行了
finally塊代碼運(yùn)行了最終返回:2
執(zhí)行流程:
程序執(zhí)行try塊中return之前(包括return語(yǔ)句中的表達(dá)式運(yùn)算)代碼,
無(wú)異常:然后再執(zhí)行finally塊,因?yàn)閒inally塊中有return所以提前退出;
有異常:執(zhí)行catch塊中return之前(包括return語(yǔ)句中的表達(dá)式運(yùn)算)代碼,再執(zhí)行finally塊。因?yàn)閒inally塊中有return所以提前退出。
結(jié)論:
得到finally中的返回值3。
總結(jié)
無(wú)論catch是否捕獲異常,finally語(yǔ)句塊都是要被執(zhí)行的。
當(dāng)try塊或catch塊return一個(gè)值,那么finally塊中的代碼會(huì)在執(zhí)行return后,返回之前執(zhí)行。(此時(shí)并沒有返回運(yùn)算后的值,而是把要返回的值暫時(shí)保存起來)。
finally中如果包含return,那么程序?qū)?strong>在這里返回,而不是通過try或catch中的return返回,返回值就不是try或catch中保存的返回值了。會(huì)直接在finally中結(jié)束方法的執(zhí)行,導(dǎo)致try、catch中的return失效。
當(dāng)try或catch,finally中都包含return的時(shí)候,要注意返回值的類型。finally修改的基本類型是不影響返回結(jié)果的,修改list、map、自定義類等引用類型時(shí),是影響返回結(jié)果的。
編譯器會(huì)對(duì)finally中的return給予警告,因?yàn)閺膄inally中返回可能會(huì)導(dǎo)致異常丟失 。如:
try { try { throw new RuntimeException("來自try塊中的異常") ; }finally{ return; } } catch (Exception e) { e.printStackTrace(System.out) ; }
這里無(wú)法捕獲 我們自定義的運(yùn)行時(shí)異常。
又如:
try { try { throw new RuntimeException("來自try塊中的異常") ; }finally{ throw new RuntimeException("來自finally塊中的異常") ; } } catch (Exception e) { e.printStackTrace(System.out) ; }
這里會(huì)丟失 第一個(gè)異常。
到此這篇關(guān)于try-catch-finally執(zhí)行順序你知道嗎的文章就介紹到這了,更多相關(guān)try-catch-finally執(zhí)行順序內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
如何讓Jackson JSON生成的數(shù)據(jù)包含的中文以u(píng)nicode方式編碼
這篇文章主要介紹了如何讓Jackson JSON生成的數(shù)據(jù)包含的中文以u(píng)nicode方式編碼。需要的朋友可以過來參考下,希望對(duì)大家有所幫助2013-12-12Java實(shí)現(xiàn)的微信公眾號(hào)獲取微信用戶信息示例
這篇文章主要介紹了Java實(shí)現(xiàn)的微信公眾號(hào)獲取微信用戶信息,結(jié)合實(shí)例形式分析了Java微信公眾號(hào)獲取微信用戶信息相關(guān)原理、步驟與操作注意事項(xiàng),需要的朋友可以參考下2019-10-10Spring Cloud下實(shí)現(xiàn)用戶鑒權(quán)的方案
Java下常用的安全框架主要有Spring Security和shiro,都可提供非常強(qiáng)大的功能,但學(xué)習(xí)成本較高。但在微服務(wù)下鑒權(quán)又會(huì)對(duì)服務(wù)有一定的入侵性。 因此,本文將介紹Spring Cloud下實(shí)現(xiàn)用戶鑒權(quán)的方案,感興趣的同學(xué)可以關(guān)注一下2021-11-11selenium高效應(yīng)對(duì)Web頁(yè)面元素刷新的實(shí)例講解
今天小編就為大家分享一篇selenium高效應(yīng)對(duì)Web頁(yè)面元素刷新的實(shí)例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-05-05解讀CommandLineRunner和@PostConstruct區(qū)別與應(yīng)用場(chǎng)景
這篇文章主要介紹了解讀CommandLineRunner和@PostConstruct區(qū)別與應(yīng)用場(chǎng)景,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12對(duì)Java的面對(duì)對(duì)象編程中對(duì)象和引用以及內(nèi)部類的理解
這篇文章主要介紹了對(duì)Java的面對(duì)對(duì)象編程中對(duì)象和引用以及內(nèi)部類的理解,需要的朋友可以參考下2016-01-01Spring注解開發(fā)@Bean和@ComponentScan使用案例
這篇文章主要介紹了Spring注解開發(fā)@Bean和@ComponentScan使用案例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09