以前在刷筆試題和麪試的時候常常會遇到或者被問到 try-catch-finally 語法塊的執行順序等問題,今天就抽空整理了一下這個知識點,而後記錄下來。java
本篇文章主要是經過舉例的方式來闡述各類狀況,我這裏根據 try-catch-finally 語法塊分爲兩種大狀況討論:try-catch 語法塊和 try-catch-finally 語句塊,而後再在每種狀況裏再去具體討論。面試
咱們能夠看看下面程序:code
public static void main(String[] args) { System.out.println(handleException0()); } /** * try,catch都有return * @return */ private static String handleException0() { try{ System.out.println("try開始"); String s = null; int length = s.charAt(0); System.out.println("try結束"); return "try塊的返回值"; }catch (Exception e){ System.out.println("捕獲到了異常"); return "catch的返回值"; } }
執行結果:io
try開始
捕獲到了異常
catch的返回值語法
分析:程序首先執行 try 塊裏面的代碼,try 塊裏面發現有異常,try 塊後面的代碼不會執行(天然也不會return),而後進入匹配異常的那個 catch 塊,而後進入 catch 塊裏面將代碼執行完畢,當執行到 catch 裏面的return 語句的時候,程序停止,而後將此 return 的最終結果返回回去。程序
這種語法塊我分爲了 4 種狀況討論,下面進行一一列舉。方法
一、第一種狀況,try 塊裏面有 return 的狀況,而且捕獲到異常im
例1:總結
public static void main(String[] args) { String result = handleException1(); System.out.println(result); } private static String handleException1() { try{ System.out.println("try開始"); String str = null; int length = str.length(); System.out.println("try結束"); }catch (Exception e){ System.out.println("捕獲到了異常"); }finally { System.out.println("finally塊執行完畢了"); } return "最終的結果"; }
例1執行的結果以下:筆試
try開始
捕獲到了異常
finally塊執行完畢了
最終的結果
例2:
public static void main(String[] args) { String result = handleException2(); System.out.println(result); } private static String handleException2() { try{ System.out.println("try開始"); String str = null; int length = str.length(); System.out.println("try結束"); return "try塊的返回值"; }catch (Exception e){ System.out.println("捕獲到了異常"); }finally { System.out.println("finally塊執行完畢了"); } return "最終的結果"; }
例2的執行結果以下:
try開始
捕獲到了異常
finally塊執行完畢了
最終的結果
分析:首先 例1 和 例2 的結果是很顯然的,當遇到異常的時候,直接進入匹配到相對應的 catch 塊,而後繼續執行 finallly 語句塊,最後將 return 結果返回回去。
第二種狀況:try塊裏面有return的狀況,可是不會捕獲到異常
例3:
思考:下面代碼try語句塊中有return語句,那麼是否執行完try語句塊就直接return退出方法了呢?
public static void main(String[] args) { String result = handleException3(); System.out.println(result); } private static String handleException3() { try{ System.out.println(""); return "try塊的返回值"; }catch (Exception e){ System.out.println("捕獲到了異常"); }finally { System.out.println("finally塊執行完畢了"); } return "最終的結果"; }
例3的執行結果以下:
finally塊執行完畢了
try塊的返回值
分析:例3的結果其實咱們能夠經過打斷點的方式去看看程序的具體執行流程,經過打斷點咱們能夠發現,代碼先執行 try塊 裏的代碼,當執行到 return 語句的時候,handleException3方法並無馬上結束,而是繼續執行finally塊裏的代碼,finally塊裏的代碼執行完後,緊接着回到 try 塊的 return 語句,再把最終結果返回回去, handleException 方法執行完畢。
第三種狀況:try塊和finally裏面都有return的狀況
例4:
public static void main(String[] args) { System.out.println(handleException4()); } /** * 狀況3:try和finally中均有return * @return */ private static String handleException4() { try{ System.out.println(""); return "try塊的返回值"; }catch (Exception e){ System.out.println("捕獲到了異常"); }finally { System.out.println("finally塊執行完畢了"); return "finally的返回值"; } // return "最終的結果";//不能再有返回值 }
例4的執行結果:
finally塊執行完畢了
finally的返回值
分析:須要注意的是,當 try 塊和 finally 裏面都有 return 的時候,在 try/catch/finally 語法塊以外不容許再有return 關鍵字。咱們仍是經過在程序中打斷點的方式來看看代碼的具體執行流程。代碼首先執行 try 塊 裏的代碼,當執行到 return 語句的時候,handleException4 方法並無馬上結束,而是繼續執行 finally 塊裏的代碼,當發現 finally 塊裏有 return 的時候,直接將 finally 裏的返回值(也就是最終結果)返回回去, handleException4 方法執行完畢。
第四種狀況:try塊,catch塊,finally塊都有return
例5:
public static void main(String[] args) { System.out.println(handleException5()); } /** * 狀況4:try,catch,finally都有return * @return */ private static String handleException5() { try{ System.out.println("try開始"); int[] array = {1, 2, 3}; int i = array[10]; System.out.println("try結束"); return "try塊的返回值"; }catch (Exception e){ e.printStackTrace();//這行代碼其實就是打印輸出異常的具體信息 System.out.println("捕獲到了異常"); return "catch的返回值"; }finally { System.out.println("finally塊執行完畢了"); return "finally的返回值"; } // return "最終的結果"; }
例5的執行結果:
try開始
捕獲到了異常
finally塊執行完畢了
finally的返回值
java.lang.ArrayIndexOutOfBoundsException: 10
at com.example.javabasic.javabasic.ExceptionAndError.TryCatchFinally.handleException5(TryCatchFinally.java:25)
at com.example.javabasic.javabasic.ExceptionAndError.TryCatchFinally.main(TryCatchFinally.java:14)
分析:程序首先執行try塊裏面的代碼,try塊裏面發現有異常,try塊後面的代碼不會執行(天然也不會return),而後進入匹配異常的那個catch塊,而後進入catch塊裏面將代碼執行完畢,當執行到catch裏面的return語句的時候,程序不會立刻終止,而是繼續執行finally塊的代碼,最後執行finally裏面的return,而後將此return的最終結果返回回去。
其實,咱們經過以上例子咱們能夠發現,無論return關鍵字在哪,finally必定會執行完畢。理論上來講try、catch、finally塊中都容許書寫return關鍵字,可是執行優先級較低的塊中的return關鍵字定義的返回值將覆蓋執行優先級較高的塊中return關鍵字定義的返回值。也就是說finally塊中定義的返回值將會覆蓋catch塊、try塊中定義的返回值;catch塊中定義的返回值將會覆蓋try塊中定義的返回值。
再換句話說若是在finally塊中經過return關鍵字定義了返回值,那麼以前全部經過return關鍵字定義的返回值都將失效——由於finally塊中的代碼必定是會執行的。
公衆號:良許Linux