我有 Java 背景,最近開始學習 Kotlin。現在我正在讀一本書“Programming Kotlin”,我找到了一個帶有 try-catch 運算式的片段。它讓我撰寫了一些簡單的函式來比較它在 Java 和 Kotlin 中的作業方式。第一個功能:
fun tryExpExplicit(throwing: Boolean): Int {
return try {
if (throwing) {
throw RuntimeException()
}
return 1
} catch (e: Exception) {
return 2
} finally {
return 3
}
}
像我預期的那樣作業并且總是回傳 3。
沒想到,當我使用隱式回傳時,行為不同
fun tryExpImplicit(throwing: Boolean): Int {
return try {
if (throwing) {
throw RuntimeException()
}
1
} catch (e: Exception) {
2
} finally {
3
}
}
并且 3 永遠不會回傳。
為什么這兩個函式的作業方式不同?
uj5u.com熱心網友回復:
與 Java 中的行為的區別在于 Kotlintry ... catch ... finally中是運算式,而不是陳述句。
評估“try-expression”的方式在規范中定義如下:
try-expression 評估評估它的主體;如果 try 主體中的任何陳述句拋出例外(E 型別),則檢查該例外以查找匹配的 catch 塊,而不是立即沿呼叫堆疊向上傳播。如果此 try 運算式的 catch 塊具有 T:>E 型別的例外引數,則在引發例外后立即評估此 catch 塊,并將例外本身作為相應引數傳遞到 catch 塊內。[...]
如果有 finally 塊,則在對所有先前的 try-expression 塊進行評估之后對其進行評估
try-expression 的值與 try 主體的最后一個運算式的值(如果沒有拋出例外)或匹配的 catch 塊的最后一個運算式的值(如果拋出并匹配例外)相同。所有其他情況意味著例外將向上傳播到呼叫堆疊,并且 try 運算式的值未定義。
注意:如上所述,finally 塊(如果存在)總是被執行,但對 try 運算式的值沒有影響。
所以當throwing為真時,try、catch、 和finally塊都被執行,但try-expression的值是catch塊中最后一個運算式的值。這解釋了“顯式”和“隱式”情況下的行為。
在“顯式回傳”的情況下,return 2執行了,但方法不能回傳那里 - finally 塊仍然必須運行!然后return 3執行,現在方法回傳。值得注意的是,外部return永遠不會被執行。您可以洗掉外部return并啟動該方法try { ...并獲得相同的結果。
在“隱式回傳”的情況下,2被評估,并且沒有副作用發生,因為它只是一個文字。然后 finally 塊運行,并被3評估,再次沒有副作用發生,因為它只是一個文字。現在我們已經完成了整個 - 運算式的評估try,根據規范,運算式的值應該是我們在 catch 塊中評估的值 - 即 2。現在我們執行return 2。
旁注:return ...也是運算式,并且它們具有Nothing(每種型別的子型別)的型別,因為它們從不計算任何東西。這就是為什么您可以return 1在“顯式回傳”情況下將 etc 寫為 try-expression 塊中的最后一行。在這種情況下,try 運算式實際上有一個型別Nothing,而外部return實際上是回傳Nothing。這很好,因為Nothing它是Int.
uj5u.com熱心網友回復:
在此處的檔案中,它說當使用 try/catch 時,運算式:
finally 塊的內容不會影響運算式的結果。
在第一個示例中,即使您的 finally 塊不影響運算式的評估,它也通過直接回傳來完全短路運算式。
在第二個示例中,finallyis 什么都不做,并且由于它不影響運算式,因此忽略該值。
在實踐中,如果你從一個塊回傳,你永遠不會撰寫從 atry和/或 catch回傳的代碼,因為這將是無用的代碼。blockfinally
uj5u.com熱心網友回復:
你可以在kotlin
fun tryExpExplicit(throwing: Boolean): Int {
return runCatching {
// do something
}.onFailure { exception ->
// similar to catch
}.onSuccess { data ->
// similar to finally
}.getOrThrow() // get the data or throw
}
內部runCatching正在使用try/catchjava 中類似的塊。你可以想到
runCatching作為try.onFailure作為catch.onSuccess作為finally
你也可以使用它的擴展來回傳值
.getOrThrow如果要回傳資料或拋出例外.getOrNull如果要回傳資料,如果拋出例外則回傳 null.getOrElse如果你想回傳資料,否則如果它拋出例外.getOrDefault如果要回傳資料或默認值,如果它拋出例外
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/461758.html
