finally塊中的程式碼什麼時候被執行
阿新 • • 發佈:2018-12-02
問題描述: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