Try-Catch-Finally代碼塊中的return
測試類的原型是這樣子的
public class TryCatchFinallyToReturn { public static void main(String[] args) { System.out.println(test()); } public static int test() { try { System.out.println("try block."); throwMethod(); return 1; } catch(Exception e) { System.out.println("catch block."); return 2; } finally { System.out.println("finally"); return 3; } } public static void throwMethod() throws Exception { } }
可以看到finally代碼塊整個大括號都出現了警告了,
finally block does not complete normally
說明finally{}中出現return是不合適的。
強行運行一下,結果是這樣的(結果1)
try block.
finally block.
3
通過斷點追蹤,try{}中的return 1已經運行到了,但是try{}正常運行結束後,finally{}必須要被執行
最後所以真正的返回值是3
變更一下測試原型,測試一下出現異常的情況
public static void throwMethod() throws Exception { System.out.println("throw."); throw new Exception(); }
運行一下(結果2)
try block. throw. catch block. finally block. 3
異常被捕獲到了catch{}中的return 2確保了運行,但是返回值依然是finall{}中的return 3。
同樣的,通過斷點追蹤發現return 2也被運行到了,但是被return 3覆蓋了
最後刪除finally{} 中的return 3
} finally { System.out.println("finally block."); }
運行一下通過調整throwMethod方法,分別測試一下正常情況和異常情況(結果3)(結果4)
try block.
finally block.
1
try block.
throw.
catch block.
finally block.
2
返回值正確了。
現在可以得到4個結論
A、運行時發生異常的那條語句再也沒有機會運行到了,原因是異常被catch()捕獲到,程序流程進入了catch{}
這點可以通過結果2看到,斷點沒有運行到return 1
B、無論try{}還是catch{}發生了什麽,finally{}中的語句一定會運行到
這點可以通過結果1234看到,"finally block."怎麽樣都是打印出來的
C、當try{}或是catch{}發生return時,方法並不是立即返回的,而是等finally{}執行完畢後,才返回。
這點可以通過結果34看到,在打印結果"1"或"2"的前一行,"finally block."被打印出來了
D、如果設計不當,使finally{}中存在return語句,那麽執行當finally{return}時,方法會直接返回,finally{}執行之前預定需要返回的返回值,會被覆蓋掉。
這點可以通過結果12看到,返回值都是finally裏的3而不是try裏的1或catch裏的2。
C、D可以如此理解,沒有返回語句的finally{}比較本分,try{}、catch{}顧及到語言限定,在返回前給了finally{}運行的機會,finally運行完畢後返回正確的值;
但編碼使另finally{}中出現返回語句,那麽finally{}就像是一個過河拆橋的人,利用try{}或是catch{}給的機會,執行了自己的返回語句,讓方法直接結束,try{return}或catch{return}再也沒有機會返回了。
Try-Catch-Finally代碼塊中的return