try-catch-finally顺序问题

使用带整型返回值的函数探讨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无关。

猜你喜欢

转载自blog.csdn.net/A1344714150/article/details/80753898