Return 與跳轉
Kotlin 有三種結構化跳轉表達式:
return
預設從最接近的封裝函數或匿名函數返回。break
終止最接近的封裝迴圈。continue
繼續到最接近的封裝迴圈的下一個步驟。
所有這些表達式都可以作為更大表達式的一部分使用:
val s = person.name ?: return
這些表達式的類型是 Nothing 類型。
Break 與 Continue 標籤
Kotlin 中的任何表達式都可以被標記為一個 標籤。 標籤的形式是識別符號後跟 @
符號,例如 abc@
或 fooBar@
。 要為表達式標記,只需在其前面添加一個標籤即可。
loop@ for (i in 1..100) {
// ...
}
現在,你可以使用標籤限定 break
或 continue
:
loop@ for (i in 1..100) {
for (j in 1..100) {
if (...) break@loop
}
}
帶有標籤限定的 break
會跳轉到標記該標籤的迴圈結束後的執行點。 continue
則會繼續到該迴圈的下一次疊代。
在某些情況下,你可以 非局部地 應用
break
和continue
而無需明確定義標籤。 這種非局部的用法在用於封裝內聯函數的 Lambda 表達式中是有效的。
Return 到標籤
在 Kotlin 中,函數可以使用函數字面量、局部函數和物件表達式進行巢狀定義。 限定 return
允許你從外部函數返回。
最重要的用例是從 Lambda 表達式返回。要從 Lambda 表達式返回,請為其標記並限定 return
:
fun foo() {
listOf(1, 2, 3, 4, 5).forEach lit@{
if (it == 3) return@lit // local return to the caller of the lambda - the forEach loop
print(it)
}
print(" done with explicit label")
}
fun main() {
foo()
}
現在,它只從 Lambda 表達式返回。通常,使用 隱式標籤 更方便,因為這種標籤的名稱與傳遞 Lambda 的函數名稱相同。
fun foo() {
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return@forEach // local return to the caller of the lambda - the forEach loop
print(it)
}
print(" done with implicit label")
}
fun main() {
foo()
}
或者,你可以用匿名函數替換 Lambda 表達式。 匿名函數中的 return
語句將從匿名函數本身返回。
fun foo() {
listOf(1, 2, 3, 4, 5).forEach(fun(value: Int) {
if (value == 3) return // local return to the caller of the anonymous function - the forEach loop
print(value)
})
print(" done with anonymous function")
}
fun main() {
foo()
}
請注意,前三個範例中局部 return 的使用方式,與常規迴圈中 continue
的使用方式相似。
break
沒有直接的等價物,但可以通過添加一個外部 run
Lambda 並從中非局部返回來模擬:
fun foo() {
run loop@{
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return@loop // non-local return from the lambda passed to run
print(it)
}
}
print(" done with nested loop")
}
fun main() {
foo()
}
此處的非局部 return 是可能的,因為巢狀的 forEach()
Lambda 作為內聯函數運行。
當返回一個值時,解析器會優先處理限定 return:
return@a 1
這意味著「在標籤 @a
處返回 1
」,而不是「返回一個帶標籤的表達式 (@a 1)
」。
在某些情況下,你可以在不使用標籤的情況下從 Lambda 表達式返回。這種 非局部 return 位於 Lambda 中,但會退出封裝的內聯函數。