1. 程式人生 > >finally塊中的程式碼什麼時候被執行

finally塊中的程式碼什麼時候被執行

問題描述:try{ }裡有一個return語句,那麼緊跟在這個try後的finally{ }中的程式碼是否會被執行?如果會的話什麼時候被執行,在return之前還是之後?

第一段程式碼:
public class Test01 {
	public static int testFinally() {
		try {
			return 1;
		} catch (Exception e) {
			return 0;
		}finally {
			System.out.println("Finally塊中的程式碼");
		}
	}
	public static void main
(String[] args) { int result = testFinally(); System.out.println(result); } } //Finally塊中的程式碼 //1

由於程式執行return就意味著結束對當前函式的呼叫並跳出這個函式體,因此任何語句要執行都只能在return前執行(除非碰到exit函式),因此finally塊裡的程式碼也是在return前執行的


第二段程式碼
public class Test01 {
	public static int testFinally() {
		try {
			return 1;
		} catch
(Exception e) { return 0; }finally { System.out.println("Finally塊中的程式碼"); return 3; } } public static void main(String[] args) { int result = testFinally(); System.out.println(result); } } //Finally塊中的程式碼 //3

當finally塊中有return語句時,將會覆蓋函式中其他return語句。


第三段程式碼
public class Test01
{ public static int testFinally() { int result = 1; try { result = 2; return result; } catch (Exception e) { return 0; }finally { result = 3; System.out.println("Finally塊中的程式碼"); } } public static void main(String[] args) { int resultVal = testFinally(); System.out.println(resultVal); } } //Finally塊中的程式碼 //2

由於在一個方法內部定義的變數都儲存在棧中,當這個函式結束後,其對應的棧就會被回收,此時在其方法體中定義的變數將不存在了,因此return在返回時不是直接返回變數的值,而是複製一份,然後返回。即,程式在呼叫return前,先把result值2複製一份儲存在一個指定的位置,然後再去執行finally塊中的程式碼,此時修改result的值將不會影響程式的返回結果。因此,對於第三段程式碼所測的基本資料型別的資料在finally塊中改變return的值對返回值沒有任何影響


如果對於引用資料型別呢?

第四段程式碼
public class Test01 {
	public static StringBuffer testFinally() {
		StringBuffer s = new StringBuffer("Hello");
		try {
			return s;
		} catch (Exception e) {
			return null;
		}finally {
			s.append(" World");
			System.out.println("Finally塊中的程式碼");
		}
	}
	public static void main(String[] args) {
		StringBuffer resultRef = testFinally();
		System.out.println(resultRef);
	}
}
//Finally塊中的程式碼
//Hello World

雖然程式在呼叫return前,先把resultRef的值複製一份s儲存到一個指定位置,然後再去執行finally塊中的程式碼,但是原s依然可以引用到該字串,所以可以改變該字串,所以得出結論:對於引用資料型別來說,在finally塊中改變return的值對返回值有影響。


引申:出現在Java程式中的finally塊是不是一定會被執行?

首先答案時否定的。

  • 當程式在進入try語句塊之前就出現異常,會直接結束。
public class Test01 {
	public static void testFinally() {
		int i = 5/0;
		try {
			System.out.println("try block");
		} catch (Exception e) {
			System.out.println("catch block");
		}finally {
			System.out.println("Finally block");
		}
	}
	public static void main(String[] args) {
		testFinally();
	}
}
/**
 * Exception in thread "main" java.lang.ArithmeticException: / by zero
 *	at Test.Test01.testFinally(Test01.java:5)
 *  at Test.Test01.main(Test01.java:15)
 */
  • 當程式在try塊中強制退出時不會去執行finally塊中的程式碼。
public class Test01 {
	public static void testFinally() {
		try {
			System.out.println("try block");
			System.exit(0);
		} catch (Exception e) {
			System.out.println("catch block");
		}finally {
			System.out.println("Finally block");
		}
	}
	public static void main(String[] args) {
		testFinally();
	}
}
//try block