使用带整型返回值的函数探讨try-catch-finally异常捕获块的执行顺序:
分六步讨论:
(1)无异常抛出时,try块有return语句,finally块无return语句
(2)无异常抛出时,try块有return语句,finally块无return语句,finally块对try块中该返回的值进行修改
(3)无异常抛出时,try块有return语句,finally块有return语句
(4)有异常抛出时,try块有return语句,catch块有return语句,finally块有return语句
(5)有异常抛出时,try块有return语句,catch块有return语句,finally块无return语句
(6)有异常抛出时,try块有return语句,catch块有return语句,finally块无return语句,finally块对catch块中该返回的值进行修改。
具体步骤:对以上六种情况,分别向getNum(int a,int b)传入a,b参数,得到num值,根据函数中的代码执行块输出语句以及最后得到的num的值判断具体顺序。
六种情况用于测试的代码如下:
(1)
package 异常捕获块执行顺序;
public class Main {
public static void main(String[] args) {
int a,b;
a=2;
b=1;
int num = getNum(a,b);
System.out.println(String.format("a的值是%d,b的值是%d,num的值是 %d",a,b,num));
}
public static int getNum(int a,int b){
int num=0;
try{
System.out.println("try块被执行");
num = a/b;
return num;
}catch(Exception e){
System.out.println("catch块被执行");
return -1;
}finally{
System.out.println("finally块被执行");
}
}
}
输出结果:
分析:传入a,b两个数,a=2,b=1,得到的返回值num是2;函数中执行了try块跟finally块,此时返回值是a/b得到的商。
结论:无异常抛出时,会先后执行try块跟finally块的代码。
(2)
package 异常捕获块执行顺序;
public class Main {
public static void main(String[] args) {
int a,b;
a=2;
b=1;
int num = getNum(a,b);
System.out.println(String.format("a的值是%d,b的值是%d,num的值是 %d",a,b,num));
}
public static int getNum(int a,int b){
int num=0;
try{
System.out.println("try块被执行");
num = a/b;
return num;
}catch(Exception e){
System.out.println("catch块被执行");
return -1;
}finally{
System.out.println("finally块被执行");
num++;
}
}
}
输出结果:
分析:函数中先执行try块代码,得到num=a/b的结果为2,到return部分时先对该结果进行了一个暂存,再执行finally块,num++,此时num为3,回到try块,return刚才开始时暂存的结果2.
结论:try中return的值为暂存值,在finally块对返回值num进行修改操作,不会影响到try里的return值
(3)
package 异常捕获块执行顺序;
public class Main {
public static void main(String[] args) {
int a,b;
a=2;
b=1;
int num = getNum(a,b);
System.out.println(String.format("a的值是%d,b的值是%d,num的值是 %d",a,b,num));
}
public static int getNum(int a,int b){
int num=0;
try{
System.out.println("try块被执行");
num = a/b;
return num;
}catch(Exception e){
System.out.println("catch块被执行");
return -1;
}finally{
System.out.println("finally块被执行");
return num+1;
}
}
}
输出结果:
分析:函数中执行了try块-finally块,得到的返回值不再是a/b的商,而是finally块返回的num+1,即try块该返回的值被finally块覆盖了。
结论:finally块的return语句会覆盖掉try块中的return语句。
(4)
package 异常捕获块执行顺序;
public class Main {
public static void main(String[] args) {
int a,b;
a=2;
b=0;
int num = getNum(a,b);
System.out.println(String.format("a的值是%d,b的值是%d,num的值是 %d",a,b,num));
}
public static int getNum(int a,int b){
int num=0;
try{
System.out.println("try块被执行");
num = a/b;
return num;
}catch(Exception e){
System.out.println("catch块被执行");
return -1;
}finally{
System.out.println("finally块被执行");
return num+1;
}
}
}
输出结果:
分析:函数中先执行try块代码,在对num进行赋值操作时抛出异常(除数不能为0,此时num仍为初始值0),被catch块捕获,执行catch块代码,暂存catch块需要返回的值,执行finally块,返回num+1,覆盖了catch块的return语句。
结论:finally块的return语句会将catch块的return语句覆盖。
(5)
package 异常捕获块执行顺序;
public class Main {
public static void main(String[] args) {
int a,b;
a=2;
b=0;
int num = getNum(a,b);
System.out.println(String.format("a的值是%d,b的值是%d,num的值是 %d",a,b,num));
}
public static int getNum(int a,int b){
int num=0;
try{
System.out.println("try块被执行");
num = a/b;
return num;
}catch(Exception e){
System.out.println("catch块被执行");
num--;
return num;
}finally{
System.out.println("finally块被执行");
}
}
}
输出结果:
分析:先执行try块,捕获到异常时执行catch块,到catch块中return语句时执行finally块代码,最后执行catch块中的return语句。
结论:finally块代码在catch返回值之前会被执行
(6)
package 异常捕获块执行顺序;
public class Main {
public static void main(String[] args) {
int a,b;
a=2;
b=0;
int num = getNum(a,b);
System.out.println(String.format("a的值是%d,b的值是%d,num的值是 %d",a,b,num));
}
public static int getNum(int a,int b){
int num=0;
try{
System.out.println("try块被执行");
num = a/b;
return num;
}catch(Exception e){
System.out.println("catch块被执行");
num--;
return num;
}finally{
System.out.println("finally块被执行");
num--;
}
}
}
输出结果:
分析:先执行try块,捕获到异常时执行catch块,num从0变为-1,到catch块中return语句时先暂存num的值,再执行finally块代码,num从-1变为-2,最后执行catch块中的return语句,得到的结果是-1。原因是此时返回的num是之前暂存的num值,finally块对num进行修改不影响之前暂存值的返回。
结论:finally块修改catch块中该返回的num时,不能影响到catch块最终返回的值。
总结:
(1)无论try块代码是否抛出异常,最终都会执行finally块代码。
(2)无异常抛出时,执行try块代码,到return语句时,会先将return的值进行一个暂存处理,再执行finally块代码;如果finally块有return语句,将会覆盖掉try块中的return语句;如果finally块无return语句,将继续回到try块执行return语句,返回一开始在try块中进行暂存的值。
(3)有异常抛出时,先执行try块代码,抛出异常时跳转到catch块,执行catch块代码;执行到catch块的return语句时,先将该返回的值进行暂存,再执行finally块语句;如果finally块有return语句,将会覆盖掉catch块中的return语句;如果finally块无return语句,将继续回到catch块执行return语句,返回刚才在catch块执行return语句时暂存的值。
(4)如果在finally块修改try/catch代码块中return返回的变量的值,不会影响到try/catch块最后的返回结果,因为try/catch块最后返回的结果是原先暂存的值,与finally修改后的num无关。