[火線解碼] 001.避免在 finally 語句塊中使用 return 語句

火線團隊推出【火線解碼】系列文章,每一篇解釋一種不規(guī)范的代碼寫法,用較短的篇幅讓大家快速的了解代碼規(guī)范問題。

001.避免在finally語句塊中使用return語句

錯誤的代碼示例:

public class Bar {
   public String foo() {
        try {
            doSomething();
        } catch (Exception e) {
            throw e;
        } finally {
            return "OK"; //觸發(fā)規(guī)則
        }
    }
}

以上代碼中的try-catch-finally是Java代碼中很常見的寫法,其中finally語句塊作為確定會執(zhí)行的語句塊,一般多用于資源的清理操作。但是文中的finally語句塊中使用了return語句,是需要避免的寫法。

為什么?

舉例說明:

public class Test02 {
    public static void main(String[] args) {
          int b=doSomething();
          System.out.println("b="+b);
      }
    
    public static int doSomething() {
        int a = 10;
        try {
             a= 8/0;
        } catch (ArithmeticException e) {
            System.out.println("捕獲到異常");
            //e.printStackTrace();
            throw e;
        } finally {
            return a;//錯誤的寫法
        }
        //return a;//正確的寫法
    }
}

代碼中在doSomething()方法中設(shè)置了一個常見的除0異常。當執(zhí)行main方法時,我們預(yù)期應(yīng)該輸出“捕獲到異?!?,并拋出異常的詳細信息。

實際該代碼輸出了“捕獲到異?!币约啊癰=10”,沒有拋出異常信息。根據(jù)輸出信息“捕獲到異?!闭Z句說明try-catch語句塊實際已經(jīng)執(zhí)行完成,但是輸出“b=10”說明程序并沒有認為doSomething()方法拋出了異常,為什么呢?

根據(jù)Java語言規(guī)范文檔14.20.2,

- If the catch block completes abruptly for reason R, then the finally block is executed. 
    - If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and reason R is discarded).

翻譯:
在一個try-catch-finally語句中,如果catch語句塊由于原因R立即結(jié)束,例如return或者出現(xiàn)異常,那么會繼續(xù)執(zhí)行finally語句塊。
當finally語句塊由于原因S立即結(jié)束,例如使用了return語句或者出現(xiàn)異常,那么try語句也會由于原因S立即結(jié)束,并且之前造成catch語句塊立即結(jié)束的原因R(出現(xiàn)異常)會被丟棄。

在JVM層面,根據(jù)JVM文檔3.13. Compiling finally,

 If a new value is thrown during execution of the finally clause, the finally clause aborts, and tryCatchFinally returns abruptly, throwing the new value to its invoker.

翻譯:
如果finally子句在執(zhí)行期間拋出一個新值,finally子句中止,整個try-catch-finally語句塊立即返回,將這個新值拋給上層調(diào)用者。

總結(jié)

在try-catch-finally語句塊中,finally語句塊中的return/拋出異常(立即結(jié)束語句)的優(yōu)先級最高,程序會優(yōu)先返回finally語句塊中的立即結(jié)束語句的結(jié)果,此時try-catch語句塊中的return/拋出異常(立即結(jié)束語句)的結(jié)果就會被丟棄掉。
所以我們在將捕獲的異常拋出給調(diào)用的上層方法處理時,如果被finally語句塊中的return語句覆蓋掉了,那么這個導致異常的錯誤情況將很難發(fā)現(xiàn)和定位。

廣告

【火線解碼】系列文章由專注于安卓代碼掃描的火線產(chǎn)品團隊提供,火線官網(wǎng):http://magic.#

—— 用火線,守住代碼底線!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,853評論 18 399
  • 異常處理機制 異常處理模型:終止模型:當異常發(fā)生時,就進入異常處理程序,處理結(jié)束并不返回異常發(fā)生位置繼續(xù)執(zhí)行;恢復(fù)...
    LilacZiyun閱讀 523評論 0 2
  • 說說電影情節(jié)。七月VS安生 就像七月說的,如果可以愛安生就像愛自己一樣,或許安生和家明會在一起,她們也都是幸福的,...
  • 我都已經(jīng)準備好寫李尋歡。因為他好寫一點。但是看著看著,我再也忍不了,便投筆從飛,去特么的李尋歡。各位看官,那我就擼...
    阿修落落閱讀 2,449評論 2 3
  • 把槍藏進風衣 乘著火車去找你 用熱吻將掠過肺的煙送你 嘗嘗吧 嘗嘗我的愁 再不回家 就殺了你
    性簡閱讀 624評論 1 2

友情鏈接更多精彩內(nèi)容