1. 程式人生 > >try-catch-finally順序問題

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無關。