java try、catch、finally及finally执行顺序详解
1.為什么要用finally
先看一個(gè)沒有finally的異常處理try-catch語句:
假設(shè)count為要使用到的資源,并且用完要求釋放此資源。那么我們可以把釋放資源的語句放到try-catch后執(zhí)行,當(dāng)前的程序不管是在執(zhí)行完try語句塊還是catch語句塊,都會順序執(zhí)行到下面釋放資源的語句。
int?count?=?0;??//初始化資源
try{
??count++;
??if(count?==?1)?throw?new?Exception("Exception?in?try");
}catch(Exception?e){
??System.out.println("catch?block");
}
count?=?0;?//釋放資源
但是,如果在try或catch中有多條return語句,那么在每條return語句之前,都要先執(zhí)行釋放資源的語句:
public?void?f()?throws?Exception?{
?int?count?=?0;??//初始化資源
?try{
???doSomething;
???statementMayCauseException;??//可能會拋出異常的語句,若異常沒有被catch,則直接拋出,也不會執(zhí)行到try-catch下面的語句
???doSomething;
???if(count?==?1)?throw?new?Exception1("E1?in?try");
???if(count?==?2)?throw?new?Exception2("E2?in?try");
?}catch(Exception1?e){
???count?=?0;?//釋放資源
???throw?e;??//再次把異常拋出,讓上一級捕獲。此時(shí)將不會執(zhí)行catch外的語句,所以要先釋放資源
?}catch(Exception2?e){
??count?=?0;?//釋放資源
??return;?//返回了,也不會執(zhí)行catch外的語句,所以要先釋放資源
?}
?count?=?0;?//釋放資源
}
這樣,就需要在每一個(gè)可能返回的地方,以及每一個(gè)可能出現(xiàn)異常而導(dǎo)致程序跳轉(zhuǎn)的地方,考慮如何釋放資源,導(dǎo)致復(fù)雜和冗余。
所以,需要finally語句。
把資源釋放或狀態(tài)還原的代碼放到finally塊中,可以保證在try和catch語句執(zhí)行完后,一定會執(zhí)行finally語句塊,而不用考慮各種復(fù)雜的跳轉(zhuǎn)情況。
int?count?=?0;
try{
?count++;
?if(count?==?1)throw?new?Exception();
}catch(Exception?e){
}finally{
?count?=?0;
}
2.finally什么時(shí)候執(zhí)行
finally在return語句之后,跳轉(zhuǎn)到上一級程序之前執(zhí)行。
public?class?Test?{?
?public?static?void?main(String[]?args)?{??
??System.out?.println(test?());??
?}???
?public?static?String?test()?{??
??try?{??
???System.out?.println("try?block");??
???return?test1?();??
??}?finally?{??
???System.out?.println("finally?block");
???//return?"finally";????
??}??
?}??
?public?static?String?test1()?{??
??System.out?.println("return?statement");??
??return?"after?return";??
?}??
}
結(jié)果:
try?block
return?statement
finally?block
after?return
分析:
1.try語句塊,return?test1(),則調(diào)用test1方法
2.test1()執(zhí)行后返回"after?return",返回值"after?return"保存在一個(gè)臨時(shí)區(qū)域里
3.執(zhí)行finally語句塊。若finally語句有返回值,則此返回值將替換掉臨時(shí)區(qū)域的返回值
4.將臨時(shí)區(qū)域的返回值送到上一級方法中。
?
親測是正確的:如果若finally語句有返回值,則此返回值將替換掉臨時(shí)區(qū)域的返回值
參考:
《thinking?in?Java》
?
http://blog.csdn.net/mymyway/article/details/7954549
?
2,驗(yàn)證finally真正執(zhí)行順序
?
package?lee;
????import?java.io.*;
????public?class?Test1{
????public?static?void?main(String?argv[]){
??????Test1?m=new?Test1();
????System.out.println(m.amethod());
????}
????public?int?amethod(){
???????try{
???????????FileInputStream?dis?=new?FileInputStream("Hello.txt");?//1,拋出異常
???????}catch?(?Exception?ex)?{
???????????????System.out.println("No?such?file?found");???//2.catch捕獲異常,并執(zhí)行
???????????????return?-1;??????????????????????????????????//4,return?返回
???????}finally{
???????????????System.out.println("Doing?finally");??//3.finally一定會執(zhí)行,在return之前。(準(zhǔn)確說,應(yīng)該是return?;語句)
???????}
????????return?0;
????}
????}
????輸出結(jié)果為:
????No?such?file?found
????Doing?finally
????-1
?
總結(jié):finally其實(shí)是僅在return?;?語句執(zhí)行前執(zhí)行,如果return?一個(gè)函數(shù),那么會先執(zhí)行函數(shù),但如果函數(shù)內(nèi)有(return?;)語句,那么finally就會在這個(gè)(return?;)語句前執(zhí)行。
ps:如果catch塊有異常向外拋出,執(zhí)行順序呢:我執(zhí)行說,你拋你得異常,我finally我的語句,我倆互不干涉,你別管我啥時(shí)執(zhí)行,但我一定會執(zhí)行的親。?=?=
?
關(guān)于finally,此時(shí),應(yīng)該很明朗了??您只需記著一點(diǎn):除非調(diào)用system.exit()讓程序退出或斷電等因素致使程序中止,否則,無論任何因素,finally塊都一定會執(zhí)行!!
?
轉(zhuǎn)載于:https://blog.51cto.com/mrwlh/1085839
總結(jié)
以上是生活随笔為你收集整理的java try、catch、finally及finally执行顺序详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: oracle学习笔记一
- 下一篇: JQuery添加扩展方法(理解$.ext