本渣今天幫師兄做筆試,讀Java程序 發現答案跟我想的完全不一樣,最後一查才發現自己想的完全是錯的
,趕緊記錄一下,希望能幫到需要的人。
在實際開發中,根據 try catch 語句的執行過程,try 語句塊和 catch 語句塊有可能不被完全執行,而有些處理代碼則要求必須執行,例如文件的關閉、釋放資源等,此時就可以將這些代碼放在 finally 語句塊中。
finally 語句可以與前面介紹的 try catch 語句塊匹配使用,語法格式如下:
try{
邏輯代碼塊
}catch(ExceptionType e){
異常處理代碼塊
}finally{
清理代碼塊
文件關閉
釋放資源
}
圖一 try catch finally
語句執行流程圖
try catch finally
語句塊的執行情況可以細分爲以下 5 種情況:
- 如果 try 代碼塊中沒有拋出異常,則執行完 try 代碼塊之後直接執行 finally 代碼塊,然後執行 try catch finally 語句塊之後的語句。
- 如果 try 代碼塊中拋出異常,並被 catch 子句捕捉,那麼在拋出異常的地方終止 try 代碼塊的執行,轉而執行相匹配的 catch 代碼塊,之後執行 finally 代碼塊。如果 finally 代碼塊中沒有拋出異常,則繼續執行 try catch finally 語句塊之後的語句;如果 finally 代碼塊中拋出異常,則把該異常傳遞給該方法的調用者。
- 如果 try 代碼塊中拋出的異常沒有被任何 catch 子句捕捉到,那麼將直接執行 finally 代碼塊中的語句,並把該異常傳遞給該方法的調用者。
- 在前面的代碼中用 System.exit() 退出運行。如果代碼在 try 內部執行一條 System.exit() 語句,則應用程序將終止而不會執行 finally。
- 如果在執行 finally 塊之前,程序所在的線程死亡,finally 塊將不被執行。
實例1:
我知道 return a++;
是先 return 再+1的,但是如果用try/finally
語句捕獲時,突然發現有三種有趣的情況:
1. return a++;
2. return ++a;
3. return a+1;
分別在finally語句會有不同的輸出。
public class test {
public static void main(String[] args) {
System.out.println("s:"+test(1));
}
static int test(int a){
try {
//依次修改此處
return a++;
//return ++a;
//return a+1;
}finally {
System.out.println("f:"+a);
}
}
}
- return a++;
f:2
s:1
- return ++a;
f:2
s:2
- return a+1;
f:1
s:2
我們知道finally語句是在方法結束前運行的,
原因:程序中try內部沒有異常的情況下,若有finally,且finally中沒有return。若在try中遇到return,則先跳去執行finally中的代碼,在回來執行try中return。
其實上述代碼反編譯字節碼之後會發現:
原來其實return後面的表達式,編譯器會創建臨時變量,操作完成再返回
import java.io.PrintStream;
public class Test
{
public Test()
{
}
public static void main(String args[])
{
System.out.println((new StringBuilder()).append("s:").append(test(1)).toString());
}
static int test(int a)
{
int i = a++;//主要改此處
System.out.println((new StringBuilder()).append("f:").append(a).toString());
return i;
Exception exception;
exception;
System.out.println((new StringBuilder()).append("f:").append(a).toString());
throw exception;
}
}
實例2:
public class TryTest {
public static void main(String[] args) {
String result = get();
System.out.println(result);
}
public static String get(){
int value = 0;
try {
System.out.println("try……");
//等式1/0 :分母爲0 的明顯錯誤 ——製造錯誤(用於拋異常)
int result = 1 / value;
return "111";
} catch (Exception e) {
System.out.println("catch……");
return "444";
} finally {
System.out.println("finally……");
return "333";
}
// return "222";
}
結果:
經過測試:
- 在通過編譯器的檢查後,如果finally中有return,則以finally中的return爲準,其他的都將失效,return之前的代碼都有效。
- 第37行的return “222” 於catch、finally中的任何一個return互斥。也就是說,在catch、finally中其中一個地方存在return,編譯器就能檢查,已符合方法的返回要求。
- catch和finally中,可同時存在return,編譯能通過。但程序以finally中的return “333”爲準,不會理睬catch中的return “444”,catch中return之前的代碼仍然生效。
實例3:以下程序不會執行 try……Catch……finally之外的return,即打印的是“111”,而不打印“222”。
public static void main(String[] args) {
// 調用 測試方法
String result = get();
// 打印 測試方法返回的結果
System.out.println(result);
}
public static String get(){
try {
System.out.println("try……");
return "111";
} catch (Exception e) {
System.out.println("catch……");
} finally {
System.out.println("finally……");
}
return "222";
}
結果:
參考文獻1:try、catch、finally中return的執行順序
參考文獻2:finally語句與return a++