JAVA try catch finally return 執行順序

JAVA try catch finally return 執行順序

參考:https://www.cnblogs.com/superFish2016/p/6687549.html

一、結論

1、不管有沒有出現異常,finally塊中代碼都會執行;
2、當try和catch中有return時,finally仍然會執行;
3、如果try、catch中有return語句,finally是在return後面的表達式運算後執行的。

  • 如果是基本數據類型、靜態變量。(此時並沒有返回finally中運算後的值,而是先把要返回的值保存起來,不管finally中的代碼怎麼樣,返回的值都不會改變,仍然是之前保存的值),所以函數返回值是在finally執行前確定的;
  • 如果是引用數據類型,那麼在finally中修改除包裝類型,會對try、catch中返回的變量有影響。
    原因:JAVA基本數據類型、對象的引用以及方法參數存放在棧中,引用對象本身放在堆中。
    • 1 寄存器:最快的存儲區,由編譯器根據需求進行分配,我們在程序中無法控制。
    • 2 棧:存放基本類型的變量數據和對象的引用以及方法參數,但對象本身不存放在棧中,而是存放在堆(new出來的對象)或者常量池中(字符串常量對象存放在常量池中。)
    • 3 堆:存放所有new出來的對象。
    • 4 靜態域:存放靜態成員(static定義的)
    • 5 常量池:存放字符串常量和基本類型常量(public static final)。

4、儘量不要在finally中使用return語句,如果使用的話,會忽略try、catch中的返回語句,也會忽略try、catch中的異常,屏蔽了錯誤的發生。
5、finally中避免再次拋出異常,一旦finally中發生異常,代碼執行將會拋出finally中的異常信息,try、catch中的異常將被忽略

所以在實際項目中,finally常常是用來關閉流或者數據庫資源的,並不額外做其他操作。

二、return

return語句用來結束循環(函數),或返回一個函數的值。
1 return, 如果什麼都不接的話,其實就是void類型函數的返回,返回後不再執行return後面的語句
如果函數執行成功返回0,不成功返回非0,一般情況下非0值常用-1來表示。
2 return 0:一般用在主函數結束時,表示程序正常終止,即告訴系統程序正常。
3 return -1::表示返回一個代數值,一般用在子函數結尾。表示程序異常終止,即告訴系統程序異常
4 return 1:與return -1相同。

三、代碼實例

3.1基本數據類型和static類型

1、沒有異常、沒有return
	public static int testBasic1() {// 10
		int i = 1;
		try {
			i++;
			System.out.println("1try block, i = " + i);// 1try block, i = 2
		} catch (Exception e) {
			i++;
			System.out.println("1catch block i = " + i);// 沒輸出
		} finally {
			i = 10;
			System.out.println("1finally block i = " + i);// 1finally block i = 10
		}
		return i;// 10
	}
2、沒有異常、有return

執行順序:try return有一個返回值 執行finally

  • 在轉去之前,try中先把要返回的結果存放到不同於i的局部變量中去,執行完finally之後,在從中取出返回結果,
  • 因此,即使finally中對變量i進行了改變,但是不會影響返回結果。
  • 它應該使用棧保存返回值。
	public static int testBasic2() {//不進入catch 返回的是2
		int i = 1;
		try {
			i++;
			System.out.println("2try block, i = " + i);//2try block, i = 2
			return i;
		} catch (Exception e) {
			i++;
			System.out.println("2catch block i = " + i);//沒輸出
			return i;
		} finally {
			i = 10;
			System.out.println("2finally block i = " + i);//2 finally block i = 10			
			// return i; 有警告
		}
	}
  • 代碼順序執行從try到finally,由於finally是無論如何都會執行的,所以try裏的語句並不會直接返回。在try語句的return塊中,return返回的引用變量並不是try語句外定義的引用變量i,而是系統重新定義了一個局部引用i’,這個引用指向了引用i對應的值,也就是2,即使在finally語句中把引用i指向了值10,因爲return返回的引用已經不是i,而是i’,所以引用i的值和try語句中的返回值無關了。
3、有異常、有return

執行順序:try-異常(try中異常後的不執行)-catch-- return有一個返回值 執行finally

  • 在轉去之前,catch中先把要返回的結果存放到不同於i的局部變量中去,執行完finally之後,在從中取出返回結果,
  • 因此,即使finally中對變量i進行了改變,但是不會影響返回結果。
  • 它應該使用棧保存返回值。
	public static int testBasic3() {//進入catch 返回的是3
		int i = 1;
		try {
			i++;
			int j = 1/0;//拋出異常 算術運算異常
			System.out.println("3try block, i = " + i);//不執行
			return i;
		} catch (Exception e) {
			i++;
			System.out.println("3catch block i = " + i);//輸出 3catch block i = 3
			return i;
		} finally {
			i = 10;
			System.out.println("3finally block i = " + i);//3finally block i = 10			
			// return i; //有警告
		}
	}
4、finally中有return
	public static int testBasic4() {//沒異常不進入catch,有異常進入catch 兩種情況返回的都是finally的10
		int i = 1;
		try {
			i++;
//			int j = 1/0;//拋出異常 算術運算異常
			System.out.println("4try block, i = " + i);//不拋出異常有輸出4try block, i = 2 //拋出異常沒輸出
			return i;
		} catch (Exception e) {
			i++;
			System.out.println("4catch block i = " + i);//不拋出異常沒輸出 //拋出異常 有輸出4catch block i = 3 
			return i;
		} finally {
			i = 10;
			System.out.println("4finally block i = " + i);//finally block i = 10			
			return i; //有警告 finally中不要有返回值
		}
	}
5、finally中有異常
	public static  int testBasic5(){//finally中有異常 控制檯報錯 Exception in thread "main" java.lang.ArithmeticException: / by zero
        int i = 1; 
        try{
            i++;
            Integer.parseInt(null);
            System.out.println("5try block, i = "+i);
            return i;
        }catch(Exception e){
            String.valueOf(null);
            System.out.println("5catch block i = "+i);
            return i;
        }finally{
            i = 10;
            int m = i / 0;//Exception in thread "main" java.lang.ArithmeticException: / by zero
            System.out.println("5finally block i = "+i);
        }
}

3.2引用數據類型

1、沒有異常、finally無return。引用數據類型
	public static  List<Object> testWrap(){;//返回[try, finally]
        List<Object> list = new ArrayList<>();
        try{
            list.add("try");
            System.out.println("try block");//try block
            return list;
        }catch(Exception e){
            list.add("catch");
            System.out.println("catch block");
            return list;
        }finally{
            list.add("finally");
            System.out.println("finally block ");//finally block 
        }
	}
  • 可以看到,finally裏對list集合的操作生效了,這是爲什麼呢。我們知道基本類型在棧中存儲,而對於非基本類型是存儲在堆中的,返回的是堆中的地址,因此內容被改變了。
2、有異常、finally無return。引用數據類型
	public static List<Object> testWrap2() {// 返回[try, catch, finally]

		List<Object> list = new ArrayList<>();
		try {
			list.add("try");
			int i = 1/0;
			System.out.println("try block");// 不輸出
			return list;
		} catch (Exception e) {
			list.add("catch");
			System.out.println("catch block");//輸出 catch block
			return list;
		} finally {
			list.add("finally");
			System.out.println("finally block ");// finally block
		}
	}
  • 可以看到,finally裏對list集合的操作生效了,這是爲什麼呢。我們知道基本類型在棧中存儲,而對於非基本類型是存儲在堆中的,返回的是堆中的地址,因此內容被改變了。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章