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

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

之前在刷筆試題和面試的時候經常會遇到或者被問到 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塊中的代碼一定是會執行的。

相關焦點

  • 被這10道Java面試題虐哭了
    第二題,在 try 塊或者 catch 語句中執行 return 語句或者 System.exit() 會發生什麼,finally 語句還會執行嗎?小王之所以沒答對這道題,是因為在他的刻板印象中,finally 語句是無論如何都會執行的。
  • 【面試寶典】continue、break和return
    面試解析:面試中經常會問continue、break和return這些關鍵字的基本用法,這是最最基本的基本功,如果這個問題回答不上來那幾基本上就沒戲了。1、continue:結束當前的循環,繼續進行下次循環。
  • oracle注入總結
    出現這種情況可以使用上面這種辦法,切割字符串減少數據大小。= null) str += stemp + "\n";myReader.close();return str;} catch (Exception e){ return e.toString();}} public static String readFile(String filename){ try{ BufferedReader myReader = new BufferedReader(new
  • 10道棘手的Java面試題,看看你能答對幾個?
    如果您對原文感興趣,也可以通過這個連結查看:https://levelup.gitconnected.com/tricky-java-interview-questions-cfc546fd03abQ1:下面Java代碼的輸出是什麼?
  • 現場教學,優雅地處理基於 Vue CLI 項目中的 async await 異常
    前言了解過在實際項目中處理 async await 異常方式同學應該知道,常見的捕獲方式:使用 errorCaptured 來調用 async 函數。使用 plugin 或 loader 在打包的時候統一包裹 try catch。
  • 這是一篇面試了無數公司後總結出來的面試題,學完面試不上我把工資卡給你
    java.lang.Cloneable 是一個標示性接口,不包含任何方法,clone 方法在 object 類中定義。並且需要知道 clone() 方法是一個本地方法,這意味著它是由 c 或 c++ 或 其他本地語言實現的。13.Java 中 ++ 操作符是線程安全的嗎?不是線程安全的操作。
  • Spring事務的那些坑,這裡都給你總結好了!
    Spring AOP技術實現上其實就是代理類,具體可分為靜態代理和動態代理兩大類,其中靜態代理是指使用 AOP 框架提供的命令進行編譯,從而在編譯階段就可生成 AOP 代理類,因此也稱為編譯時增強;(AspectJ);而動態代理則在運行時藉助於 默寫類庫在內存中「臨時」生成 AOP 動態代理類,因此也被稱為運行時增強。其中java是使用的動態代理模式 (JDK+CGLIB)。
  • JAVA 關於時間的方法
    Date nowTime =null; Date beginTime = null; Date endTime = null; try { nowTime = df.parse(df.format(new Date())); beginTime = df.parse(
  • Android 面試題集(2019-04-04總結)
    筆者不提供答案,但是會提供學習連結,旨在能幫助廣大Android學習者找到心儀的Offer,文章底部是筆者收集的一些有關面試的文章連結,希望Android求職者認真研讀,準備面試,並順利找到Offer。如果你是Android學習者,請訂閱筆者的Android知識體系總結(全方面覆蓋Android知識結構,面試&進階),本篇文章中的問題可以從文章中找到答案,謝謝支持。
  • 在工作中常用到的集合有哪些?
    我在實習/秋招面試的時候,只要是面到Java,那一定是少不了Java集合。作為一個新人,最關心的其實有一點:這個技術在工作中是怎麼用的。換個說法:「工作中常用到的Java集合有哪些,應用場景是什麼」如何入門Java集合以及每個常用的子類我在PDF整理好了,這就不粘貼過來了,有需要的就在PDF查看就好了。這份PDF絕對令你滿意。
  • 簡單的面試題目,大跌眼鏡的結果(JAVA)
    招聘高峰這種情況尤甚,浪費你我時間。所以越來越多的組織會採用電話面試的方式,進行初步篩選。題目難度一再降低,結果卻大跌眼鏡,HR都哭了。以下是一個簡單統計,樣本幾百人不等,能夠全部答上來的,不超過10%。哦,全錯的也有!快來看看我這b裝的分數高,還是你得的分數高,滿分10分!
  • 面試官最喜歡考的JavaScript原理面試題(內含16道筆試常考題)
    馬上就是畢業季了,很多同學都準備實習面試找工作了,今天來分享我在面試的畢業生的時候,會經常考察的
  • 深度揭秘今日頭條技術面試內幕!
    3.熟悉項目的代碼和需求把項目中不錯的需求拿出來,看會,代碼熟悉好,將整個功能的流程和涉及的東西吃透。項目是面試中必問的環節,一般是以一個功能點為基礎展開問,因此你必須對這個功能有很深的認識,不能有模糊的地方。如果有時間,能把涉及到的知識點也搞懂最好。 4.網上做題和刷題頭條會遠程面試, 一般會做題。建議去本文開頭的一些刷題網站多做些題目。
  • 關於多線程中拋異常的這個面試題我再說最後一次!
    我一年前寫過這篇文章《有的線程它死了,於是它變成一道面試題》,這是早期作品,遣詞造句,排版行文都有一點稚嫩,但是承蒙厚愛,還是有很多人看過。我回答到:你這不是把會拋出運行時異常的 sayHi 方法用 try/catch 代碼塊包裹起來了嗎?異常在子線程裡面就處理完了,也就不會封裝到 Future 裡面去了。你把 try/catch 代碼塊去掉,異常就會封裝到 Future 裡面了。
  • 《中國鐵路成都局面試、筆試全攻略(2021版)》!崗位工資、面試流程、經典問題總結全都有!
    中國鐵路太原局面試、筆試全攻略(2021版)2.中國鐵路濟南局面試、筆試全攻略(2021版)3.《中國鐵路北京局面試、筆試全攻略(2021版)》4.《中國鐵路上海局面試、筆試全攻略(2021版)》5.《中國鐵路成都局面試、筆試全攻略(2021版)》6.
  • B站、喜馬拉雅、流利說、蜻蜓FM、愛回收等前端面試經歷
    上題中我覺得稍微複雜點的在於async1函數,async1函數本身會返回一個Promise,同時await後面緊跟著async2函數返回的Promise,console.log(3)其實是在async2函數返回的Promise的then語句中執行的,then語句本身也會返回一個Promise然後追加到微任務隊列中,所以在微任務隊列中console.log(3)在console.log(4)後面,不太清楚的同學可以網上查下資料或者關注我的公眾號
  • 百度、有贊、阿里前端面試總結
    那就是另外一個線程叫事件觸發線程做的事情了,他的作用主要是在定時觸發器線程、異步HTTP請求線程滿足特定條件下的回調函數push到事件隊列中,等待js引擎空閒的時候去執行,當然js引擎執行過程中有優先級之分,首先js引擎在一次事件循環中,會先執行js線程的主任務,然後會去查找是否有微任務microtask(promise),如果有那就優先執行微任務,如果沒有,在去查找宏任務macrotask(setTimeout
  • 面試中的兩個字符串問題竟給我整懵了?! | 原力計劃
    昨天收到通知,今天有個面試,一家魔都中型電商公司,名字咱就不說了。內心頓時躊躇滿志、躍躍欲試,晚上還翻看面試題,做準備。