以前在刷筆試題和麪試的時候常常會遇到或者被問到 try-catch-finally 語法塊的執行順序等問題,今天就抽空整理了一下這個知識點,而後記錄下來。java
本篇文章主要是經過舉例的方式來闡述各類狀況,我這裏根據 try-catch-finally 語法塊分爲兩種大狀況討論:try-catch 語法塊和 try-catch-finally 語句塊,而後再在每種狀況裏再去具體討論。程序員
咱們能夠看看下面程序:面試
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的返回值";
}
}複製代碼
執行結果:架構
try開始 捕獲到了異常 catch的返回值學習
分析:程序首先執行 try 塊裏面的代碼,try 塊裏面發現有異常,try 塊後面的代碼不會執行(天然也不會return),而後進入匹配異常的那個 catch 塊,而後進入 catch 塊裏面將代碼執行完畢,當執行到 catch 裏面的return 語句的時候,程序停止,而後將此 return 的最終結果返回回去。網站
這種語法塊我分爲了 4 種狀況討論,下面進行一一列舉。spa
一、第一種狀況,try 塊裏面有 return 的狀況,而且捕獲到異常code
例1:orm
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執行的結果以下:cdn
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學習路線圖,因而我根據本身的經驗,利用業餘時間熬夜肝了一個月,整理了一份電子書。不管你是面試仍是自我提高,相信都會對你有幫助!目錄以下:
免費送給你們,只求你們金指給我點個贊!
也但願有小夥伴能加入我,把這份電子書作得更完美!
推薦閱讀: