Java筆試面試總結—try、catch、finally語句中有return 的各類情況

2021-03-02 程式設計師資源社區
前言

之前在刷筆試題和面試的時候經常會遇到或者被問到 try-catch-finally  語法塊的執行順序等問題,今天就抽空整理了一下這個知識點,然後記錄下來。

正文

本篇文章主要是通過舉例的方式來闡述各種情況,我這裡根據 try-catch-finally 語法塊分為兩種大情況討論:try-catch 語法塊和 try-catch-finally 語句塊,然後再在每種情況裡再去具體討論。

一、try-catch  語句塊

我們可以看看下面程序:

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 的最終結果返回回去。

二、try-catch-finally 語句塊

這種語法塊我分為了 4 種情況討論,下面進行一一列舉。

1、第一種情況,try 塊裡面有 return 的情況,並且捕獲到異常

例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塊中的代碼一定是會執行的。

相關焦點

  • Java面試題:try-catch-finally中return的用法
    執行結果從結果分析看,catch中的return前執行了finally,並且在執行finally前,return的值已經確定。總結如下:finally塊的語句在try或catch中的return語句執行之後返回之前執行,若finally裡也有return語句則覆蓋try或catch中的return語句直接返回;若finally中沒有return則返回try或者catch中的已確定的return值。
  • Java 中關於 try、catch、finally 中的細節分析
    可能jvm認為一個方法裡面有兩個return語句並沒有太大的意義,所以try中的return語句給忽略了,直接起作用的是finally中的return語句,所以這次返回的是finally。,這個例子裡面finally 語句裡面有return語句塊。
  • java中關於try、catch、finally中的細節分析
    按照第一段代碼的解釋,先進行try{}語句,然後在return之前把當前的t的值try保存到一個變量t',然後執行finally語句塊,修改了變量t的值,在返回變量t。這裡面有兩個return語句,但是程序到底返回的是try 還是 finally。
  • Java中關於try、catch、finally中的細節分析
    按照第一段代碼的解釋,先進行try{}語句,然後在return之前把當前的t的值try保存到一個變量t',然後執行finally語句塊,修改了變量t的值,在返回變量t。這裡面有兩個return語句,但是程序到底返回的是try 還是 finally。
  • 面試官:當return遇到try、catch、finally時會發生什麼?
    1.return的作用在Java中的return語句和方法有密切的關係,return語句用在方法中,有兩個作用,一個是返回方法指定類型的值(這個值總是確定的),一個是結束方法的執行(僅僅一個return語句)。
  • java的try、catch、finally
    這個時候就是java中的try、catch、finally大展身手的時候了。說到try、catch、finally,大家看看下面這段代碼,最後執行輸出的結果應該是什麼呢?帶著這個問題,我們往下看看吧。try對應的大括號包含的代碼塊中。
  • Java finally語句到底是在return之前還是之後執行?
    網上有很多人探討Java中異常捕獲機制try…catch…finally塊中的finally語句是不是一定會被執行?(2)在try塊中有System.exit(0);這樣的語句,System.exit(0);是終止Java虛擬機JVM的,連JVM都停止了,所有都結束了,當然finally語句也不會被執行到。當然還有很多人探討Finally語句的執行與return的關係,頗為讓人迷惑,不知道finally語句是在try的return之前執行還是之後執行?
  • 為什麼不推薦使用try-catch-finally處理Java異常?
    這篇文章是我近期看了《Effective java》一書中總結的,來自其中第九條。為了對其理解的更加透徹,因此重新分析了一下,並加入了一些其他點。而關閉的方法有很多種。比如finalizer、try-catch-finally、try-with-resources等等。
  • try-catch-finally中的4個巨坑,老程式設計師也搞不定!
    坑1:finally中使用return若在 finally 中使用 return,那麼即使 try-catch 中有 return 操作,也不會立馬返回結果,而是再執行完 finally 中的語句再返回。
  • 三道try-catch-finally題目,面試妥妥的
    try-catch-finally題目分析:1.執行 foo(0)時,不滿足 try 語句塊中的 if 語句,所以不會拋出異常,執行 finally 語句。output=「34」2.執行 foo(1)時,滿足 try 中的 If 語句,拋出異常,在 catch 中進行異常處理,雖然有 return 語句,但是 finally 中的內容必須執行,也就是說要先執行了 finally 才進行 return 操作,return 後 output += 「4」將不會再執行。所以output="23".
  • 為什麼推薦使用try-with-resources代替try-finally
    這篇文章是我近期看了《Effective java》一書中總結的,來自其中第九條。為了對其理解的更加透徹,因此重新分析了一下,並加入了一些其他點。而關閉的方法有很多種。比如finalizer、try-catch-finally、try-with-resources等等。
  • Java代碼的finally語句塊中,這個語句要慎用
    用Java語言開發系統時,經常會需要對異常做一些處理,就會用到try……catch……語句。而有很多的時候,這樣的語句不論出現沒出現異常都要最終執行一些操作,比如流的關閉。此時就需要用到finally語句塊了。
  • 【159期】Java中的finally一定會被執行嗎?
    一、前言因為這次面試有問到一些同學finally的問題,發現自己這塊好像有點記不太清楚了,有的點可能還給人家說錯了,一度弄得場面有些尷尬。當然這個情況是比較極端的,記住就行,沒事不要亂整這個。最後總結一下:不管是給try塊中造了個異常,還是在try塊中進行return,我們發現finally塊還是會執行的。因為異常處理設計初衷就是讓finally塊始終執行。這個總結在finally的執行時機得到證明。
  • Java面試總結之Exception
    java中給我們提供了2種處理異常的方法,第一種是通過try......catch......finally的方式進行捕獲處理,第二種是通過throws向上拋出。至於什麼時候捕獲,什麼時候拋出需要進行權衡。你平時項目中是如何處理異常的?
  • 字節碼層面理解try、catch、finally
    面試中經常有關於try、catch、finally相關的問題,今天從字節碼層面了解他們的運行流程。簡單代碼直接上測試簡單代碼,如下圖:這裡是一個簡單的測試代碼,代碼中有三個異常和一個finally,這裡用一個int數組來替代對象,面試中經常會問最終會返回數組(對象)的值是多少?
  • 如何處理不同情形下 return 和 finally 的執行順序?
    語句不影響最終返回值,即返回值在finally前就決定  詳細講解,此處細分為2種情況:    try中有return、無拋出異常;    try中有return、拋出異常 、catch有return。
  • 這道面試題,出錯率90%
    大多數公司針對初級、中級都會有筆試的這個環節,甚至很多高級面試也存在筆試環節。對於筆試大家千萬不要掉以輕心,筆試題做不好,很有可能面試就黃了或者隨便找個面試官應付一下就可以回去等通知了。今天我們分享的這個面試題,出現的頻率是相當高。
  • 跟我學java編程—Java異常處理語句finally的用法
    前面講過,如果try語句塊中存在異常,則異常之後的代碼將不再執行。但在某些特定的情況下,不管是否有異常發生,總是要求某些特定的代碼必須被執行。例如,程序中執行資料庫連接的代碼,不管對資料庫的操作是否成功,最後都要關閉資料庫的連接以釋放內存資源,這就需要用到finally語句。
  • 【007期】JavaSE面試題(七):異常
    的提褲姐,今天這篇是面試系列的第七篇,主要總結了JavaSE中異常類相關面試題,在後續,會沿著第一篇開篇的知識線路一直總結下去,做到日更!或者只是使⽤e.printStacktractry()裡面有⼀個return語句, 那麼後面的finally{}裡面的代碼會不會被執行?什麼時候執行,return前還是return後?如果try中有return語句, 那麼finally中的代碼還是會執⾏。
  • 面試須知(8):C#的異常處理機制(try...catch...finally)
    在 C# 語言中異常與異常處理語句包括三種形式,即 try catch、try finally、try catch finally。在上述三種異常處理的形式中所用到關鍵字其含義如下:try:一個 try 塊標識了一個將被激活的特定的異常的代碼塊。後跟一個或多個 catch 塊。