简书 空格Ctrl
转载请注明原创出处,谢谢!
从这说起
日常编码中,被问到一个有关try/catch/finally的执行顺序问题,如果在try中return的是一个有返回值的方法,那么try/catch/finally的执行顺序是怎样的?
在分析上述问题之前,先用几个例子对try/catch/finally进行简要说明
语法
try {
//将可能引发异常的代码写在try语句块中
} catch (Exception e) {
//捕获异常后进行后续处理,可有多个catch
} finally {
//无论是否有异常,finally中的语句块是必执行的。
//finally可有可无,根据具体情况而定,一个try/catch/finally结构最多只能有一个finally
}
举例:
案例1
try {
flag = "point1";
System.out.println(flag);
// throw new Exception();
} catch (Exception e) {
flag = "point2";
System.out.println(flag);
}
输出结果为:
point1
若在try语句块中加入throw new Exception();
则输出结果为:
point1
point2
即先执行try语句块,若try语句块中抛出异常再由catch捕获,执行catch语句块。若try语句块中在抛出异常的代码后还有语句,则这些语句不再执行。
案例二
try{
flag = "point1";
System.out.println(flag);
}finally {
flag = "point2";
System.out.println(flag);
}
输出结果为:
point1
point2
即先执行try语句块,再执行finally语句块。
注意:try{}后面必须与catch或finally组合,否则编译不会通过。
案例三
try {
flag = "point1";
System.out.println(flag);
throw new Exception();
} catch (Exception e) {
flag = "point2";
System.out.println(flag);
} finally {
flag = "point3";
System.out.println(flag);
}
输出结果为:
point1
point2
point3
即先执行try语句块,catch捕捉try中的异常后执行catch中的语句块,最后执行finally中的语句块。
让return参与进来,就有了案例四和案例五。
案例四
@Test
public void testMain(){
System.out.println(test4());
}
public static String test4(){
String flag;
try {
flag = "point1";
System.out.println(flag);
return flag;//throw new Exception();
} catch (Exception e) {
flag = "point2";
System.out.println(flag);
return flag;
} finally {
flag = "point3";
System.out.println(flag);
}
}
输出结果为:
point1
point3
point1
如果将try语句块中的return flag;
注释掉,抛出异常throw new Exception();
则输出的结果为:
point1
point2
point3
point2
这个时候就有这么一个问题“为什么最后一个输出的值不是'point3'呢?”
就案例4未注释掉return flag;
,未抛异常情况的代码在编译后生成*.class文件代码如下
@Test
public void testMain() {
System.out.println(test4());
}
public static String test4() {
String flag;
String var2;
try {
flag = "point1";
System.out.println(flag);
String e = flag;
return e;
} catch (Exception var6) {
flag = "point2";
System.out.println(flag);
var2 = flag;
} finally {
flag = "point3";
System.out.println(flag);
}
return var2;
}
即在try语句块正常执行,且存在返回值时,在执行return与finally方法之前,先将flag对象的值赋予e对象,在执行完finally方法后,回到try方法执行return e返回。
若案例4注释掉return flag;
,且抛出异常时,生成*.class文件中的代码如下
@Test
public void testMain() {
System.out.println(test4());
}
public static String test4() {
String flag;
String var2;
try {
flag = "point1";
System.out.println(flag);
throw new Exception();
} catch (Exception var6) {
flag = "point2";
System.out.println(flag);
var2 = flag;
} finally {
flag = "point3";
System.out.println(flag);
}
return var2;
}
即在捕捉try语句块中抛出的异常后执行catch语句块中代码,这里将flag的值赋值给var2,然后执行finally语句块,在try/catch/finally结构执行完毕后return var2。
回到最初被问到的问题:如果在try中return的是一个有返回值的方法,那么try/catch/finally的执行顺序是怎样的?
案例五
@Test
public void testMain(){
System.out.println(test5());
}
public static String change(String flag){
flag = "change";
return flag;
}
public static String test5(){
String flag;
try {
flag = "point1";
System.out.println(flag);
return change(flag);
} catch (Exception e) {
flag = "point2";
System.out.println(flag);
return flag;
} finally {
flag = "point3";
System.out.println(flag);
}
}
输出结果为:
point1
change
point3
change
生成的*.class文件中相关代码如下
@Test
public void testMain() {
System.out.println(test5());
}
public static String change(String flag) {
flag = "change";
System.out.println(flag);
return flag;
}
public static String test5() {
String flag;
String var2;
try {
flag = "point1";
System.out.println(flag);
String e = change(flag);
return e;
} catch (Exception var6) {
flag = "point2";
System.out.println(flag);
var2 = flag;
} finally {
flag = "point3";
System.out.println(flag);
}
return var2;
}
这里其实和案例四相同,只是先将return的对象change()方法先执行得到返回值,再将返回值赋予e暂存,执行完finally语句块后return e。
若try语句块中抛出异常,在catch语句块中return change(flag);
,同理。
初次写文章,多少会有一些不足之处,望建议与指正,谢谢。