簡體   English   中英

Java try-finally返回設計問題

[英]Java try-finally return design question

在Java中,try {...} finally {...}對我來說有些不直觀。 如另一個問題所示, 最終總是在Java中執行嗎? ,如果try塊中有return語句,則在定義finally塊時將忽略它。 例如,功能

boolean test () {
    try {
        return true;
    }
    finally {
        return false;
    }
}

總是會返回false。 我的問題:這是為什么? 這個由Java做出的設計決策背后有一個特定的哲學嗎? 我很感激任何見解,謝謝。

編輯:我特別感興趣的是'為什么'Java認為可以違反我定義的語義。 如果我在try塊中'返回',那么該方法應該在那里返回。 但是JVM決定忽略我的指令並從一個實際尚未到達的子程序返回。

從技術上講,如果定義finally塊,則try塊中的return不會被忽略,只有當finally塊也包含return

這是一個可疑的設計決策,回想起來可能是一個錯誤(很像默認情況下引用是可空/可變的,並且根據一些情況,檢查異常)。 在許多方面,這種行為與finally意味着什么的口語理解完全一致 - “無論事先在try塊中發生什么,總是運行此代碼。” 因此,如果從finallyreturn true ,則整體效果必須始終為true,不是嗎?

一般來說,這很少是一個很好的習慣用法,你應該使用finally塊來清理/關閉資源,但很少從它們返回一個值。

如果finally塊中的代碼突然結束,則它會從try塊更改返回值/異常。 這被認為是不好的做法,你不應該這樣做。

在其他地方,這也在Java Puzzlers書中討論過。

如果使用-Xlint調用javac,則會生成相應的警告,指示不應從finally子句調用return。 例如(使用上面的test()方法編譯一個簡單的類):

javac -Xlint foo.java
foo.java:13: warning: [finally] finally clause cannot complete normally
    }
^
1 warning

檢查這個以供參考最后總是在Java中執行嗎?

“通過首先執行try塊來執行帶有finally塊的try語句。然后有一個選擇:
如果try塊的執行正常完成,[...]
如果由於拋出值V而突然完成try塊的執行,[...]
如果try塊的執行由於任何其他原因R突然完成,則執行finally塊。 然后有一個選擇:
如果finally塊正常完成,則try語句突然完成,原因是R.
如果finally塊因為S而突然完成,則try語句突然完成,原因是S(並且原因R被丟棄)。“

finally構造是JLS提供的一種工具,用於處理容易出現異常的代碼。 開發人員可以利用此工具確保從異常中恢復正常。 以你所描述的方式使用finally結構並不是一個好的做法。 就此而言,從finally塊中return任何東西永遠都不是好事。
所以當你asekd時,“ 哲學 ”是處理任何突然完成的代碼。 如果返回某個值作為處理這種狀態的一部分是必需的,那應該在catch塊內完成。

finally目的:

  • Java人員finally創建了關閉操作的塊,必須在兩種情況下執行(例如發生異常或沒有異常)。

  • 建議不要在finally塊中使用return語句,因為它會覆蓋catchtry塊的return語句。 並警告“ 最后阻止不能正常完成

  • finally塊只有當trycatch都沒有return語句時才應該有return語句。

  • 如果trycatch都有不同的值,那么我們不應該在finally塊中保留任何東西,

  • 如果我們在trycatch塊中返回相同的值,那么最好保持finally返回並在trycatch塊中刪除return。
  • 如果finally拋出任何異常,那么該塊內的return將不會執行。

finally塊只有在以下情況下才會執行:

  • 在調用System.exit()時
  • 殺人過程
  • 應用程序/環境崩潰
  • stackoverflow /無限循環

盡管finally塊是用於關閉資源的,並且返回語句通常不應該存在,並且Eclipse警告“最后塊不能正常完成”,我發現在某些情況下仍然需要“最終返回”。

ResponseType response = new ResponseType();
try{
    //set some properties of the response object.
    response.setStatus(1);
    //return response;
}catch (Exception e){
    //Some other properties of the response object according to the exception.
    response.setStatus(0);
    //return response;
}finally{
    return response;
}

如果我不將finally子句放在finally塊中,我將不得不在try和catch塊中重復它,並且當前代碼更清晰一點。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM