返回與跳轉
Kotlin 有三種結構化的跳轉運算式:
return預設從最接近的封閉函式或 匿名函式 返回。break結束最接近的封閉迴圈。continue進入最接近封閉迴圈的下一個反覆運算步驟。
所有這些運算式都可以作為大型運算式的一部分:
val s = person.name ?: return這些運算式的型別是 Nothing 型別。
Break 與 continue 標籤
Kotlin 中的任何運算式都可以標記 標籤 (label)。 標籤的格式為識別符號後跟 @ 符號,例如 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 則會進入該迴圈的下一個反覆運算。
在某些情況下,你可以 非區域地 (non-locally) 套用
break和continue而無需明確定義標籤。 此類非區域用法在用於封閉 內嵌函式 的 Lambda 運算式中是有效的。
返回至標籤
在 Kotlin 中,函式可以透過函式常值、區域函式和物件運算式進行巢狀。 限定的 return 允許你從外部函式返回。
最重要的使用案例是從 Lambda 運算式返回。要從 Lambda 運算式返回,請對其加上標籤並限定 return:
fun foo() {
listOf(1, 2, 3, 4, 5).forEach lit@{
if (it == 3) return@lit // 區域返回至 Lambda 的呼叫者 - forEach 迴圈
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 // 區域返回至 Lambda 的呼叫者 - forEach 迴圈
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 // 區域返回至匿名函式的呼叫者 - forEach 迴圈
print(value)
})
print(" done with anonymous function")
}
fun main() {
foo()
}請注意,前三個範例中區域返回的使用方式與一般迴圈中 continue 的使用方式類似。
對於 break 沒有直接的等價物,但可以透過新增一個外層的 run Lambda 並從中進行非區域返回來模擬:
fun foo() {
run loop@{
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return@loop // 從傳遞給 run 的 Lambda 進行非區域返回
print(it)
}
}
print(" done with nested loop")
}
fun main() {
foo()
}此處的非區域返回是可行的,因為巢狀的 forEach() Lambda 扮演了 內嵌函式 的角色。
當傳回一個值時,剖析器會優先採用限定的返回:
return@a 1這表示「在標籤 @a 處傳回 1」,而不是「傳回一個標記標籤的運算式 (@a 1)」。
在某些情況下,你可以從 Lambda 運算式返回而無需使用標籤。此類 非區域 返回位於 Lambda 中,但會退出封閉的 內嵌函式。
