读书人

java中的try-catch finally实施顺序

发布时间: 2013-03-06 16:20:31 作者: rapoo

java中的try-catch finally执行顺序

先看一个没有finally的异常处理try-catch语句:
假设count为要使用到的资源,并且用完要求释放此资源。那么我们可以把释放资源的语句放到try-catch后执行,当前的程序不管是在执行完try语句块还是catch语句块,都会顺序执行到下面释放资源的语句。
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语句之前,都要先执行释放资源的语句:
public?void?f()?throws?Exception?{
?int?count?=?0;??//初始化资源
?try{
???doSomething;
???statementMayCauseException;??//可能会抛出异常的语句,若异常没有被catch,则直接抛出,也不会执行到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;??//再次把异常抛出,让上一级捕获。此时将不会执行catch外的语句,所以要先释放资源
?}catch(Exception2?e){
??count?=?0;?//释放资源
??return;?//返回了,也不会执行catch外的语句,所以要先释放资源
?}
?count?=?0;?//释放资源
}
这样,就需要在每一个可能返回的地方,以及每一个可能出现异常而导致程序跳转的地方,考虑如何释放资源,导致复杂和冗余。

所以,需要finally语句。
把资源释放或状态还原的代码放到finally块中,可以保证在try和catch语句执行完后,一定会执行finally语句块,而不用考虑各种复杂的跳转情况。
int?count?=?0;
try{
?count++;
?if(count?==?1)throw?new?Exception();
}catch(Exception?e){
}finally{
?count?=?0;
}

2.finally什么时候执行
finally在return语句之后,跳转到上一级程序之前执行。
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";??
?}??
}
结果:
try?block
return?statement
finally?block
after?return

分析:
1.try语句块,return?test1(),则调用test1方法
2.test1()执行后返回"after?return",返回值"after?return"保存在一个临时区域里
3.执行finally语句块。若finally语句有返回值,则此返回值将替换掉临时区域的返回值
4.将临时区域的返回值送到上一级方法中。

?

亲测是正确的:如果若finally语句有返回值,则此返回值将替换掉临时区域的返回值
参考:
《thinking?in?Java》

http://blog.csdn.net/mymyway/article/details/7954549

?

2,验证finally真正执行顺序

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捕获异常,并执行
???????????????return?-1;??????????????????????????????????//4,return?返回
???????}finally{
???????????????System.out.println("Doing?finally");??//3.finally一定会执行,在return之前。(准确说,应该是return?;语句)

???????}
????????return?0;
????}
????}

????输出结果为:

????No?such?file?found
????Doing?finally
????-1

?

总结:finally其实是仅在return?;?语句执行前执行,如果return?一个函数,那么会先执行函数,但如果函数内有(return?;)语句,那么finally就会在这个(return?;)语句前执行。

ps:如果catch块有异常向外抛出,执行顺序呢:我执行说,你抛你得异常,我finally我的语句,我俩互不干涉,你别管我啥时执行,但我一定会执行的亲。?=?=

关于finally,此时,应该很明朗了??您只需记着一点:除非调用system.exit()让程序退出或断电等因素致使程序中止,否则,无论任何因素,finally块都一定会执行!!

读书人网 >编程

热点推荐