Kotlin 控制流(二):返回和跳转

Kotlin 控制流(一):条件和循环

Kotlin 中有三个结构跳转表达式:

  • 默认情况下,return 会从最近的外层函数或匿名函数中返回。

  • break会终止最近的循环

  • continue 会继续执行最近的外层循环的下一次迭代

这些表达式可以作为更大的表达式的一部分:

kotlin 复制代码
val s = person.name ?: return

这些表达式是Nothing类型

Break and continue 标签

在 Kotlin 中所有的表达式都可以标记一个标签,标签由@标记,比如abc@ 或者 fooBar@。使用的时候只需要把标签写在表达式的前面即可。

kotlin 复制代码
loop@ for (i in 1..100) {
    // ...
}

现在,可以使用标签来限定 break 或者 continue 的作用范围:

kotlin 复制代码
loop@ for (i in 1..100) {
    for (j in 1..100) {
        if (...) break@loop
    }
}

用标签限定的 break 会跳转到被该标签标记的循环之后的执行点;而用标签限定的 continue 则会继续执行被该标签标记的循环的下一次迭代。

举个例子吧:

kotlin 复制代码
outerLoop: for (let i = 0; i < 3; i++) {
  console.log(`外层循环 i = ${i}`);
  innerLoop: for (let j = 0; j < 3; j++) {
    if (i === 1 && j === 1) {
      break outerLoop; // 跳转到 outerLoop 循环之后
      // continue outerLoop; // 直接进入 outerLoop 的下一次迭代(i 变为 2)
    }
    console.log(`  内层循环 j = ${j}`);
  }
}
console.log("循环结束");

循环结束的时候 i 是 1,不是 2。

Return 标签

在 Kotlin,可以通过函数字面量、局部函数和对象表达式来实现函数嵌套。带限定符的 return 允许开发者从外层函数中返回。

带标签的返回最重要的使用场景是从 lambda 表达式返回。可以给 lambda 表达式添加标签,然后通过 return 来限定作用范围:

kotlin 复制代码
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")
}
//1245 done with explicit label
仅仅是return了lit

一般情况下,使用隐式标签会更便捷,因为这类标签与接收该 lambda 的函数同名。

kotlin 复制代码
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")
}
1245 done with implicit label
仅仅是return了forEach

当然了,也可以返回匿名函数,作用同上。

上面的局部 return 的用法,与常规循环中 continue 的作用类似。

目前没有与 break 直接对应的语法,但可以通过添加一个外层的 run lambda,并从该 lambda 中进行非局部返回来模拟 break 的效果:

kotlin 复制代码
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")
}
//12 done with nested loop
直接将loop返回

此处之所以能实现非局部返回,是因为嵌套的 forEach() 所接收的 lambda 是作为内联函数(inline function) 运行的。

当需要返回一个值时,语法解析器会优先识别带限定符的 return(qualified return)(即 return@标签名 形式),而非默认的穿透式 return。

kotlin 复制代码
return@a 1

这意味着 "在标签 @a 处返回值 1",而非 "返回一个带标签的表达式 (@a 1)"。

kotlin 复制代码
fun example() {
    val result = listOf(1, 2, 3).map a@{  // map 会处理 lambda 的返回值
        if (it == 2) {
            return@a 100  // 在 @a 标签处返回 100(仅退出当前 lambda,作为 map 的转换结果)
        }
        it  // 其他元素保持原值
    }
    println(result)  // 输出:[1, 100, 3]
}

原文

相关推荐
诺诺Okami1 小时前
Android Framework-WMS-从setContentView开始
android
前行的小黑炭2 小时前
Android :Compose如何监听生命周期?NavHostController和我们传统的Activity的任务栈有什么不同?
android·kotlin·app
Lei活在当下10 小时前
【业务场景架构实战】5. 使用 Flow 模式传递状态过程中的思考点
android·架构·android jetpack
前行的小黑炭13 小时前
Android 关于状态栏的内容:开启沉浸式页面内容被状态栏遮盖;状态栏暗亮色设置;
android·kotlin·app
用户0917 小时前
Flutter构建速度深度优化指南
android·flutter·ios
PenguinLetsGo17 小时前
关于「幽灵调用」一事第三弹:完结?
android
雨白21 小时前
Android 多线程:理解 Handler 与 Looper 机制
android
sweetying1 天前
30了,人生按部就班
android·程序员
用户2018792831671 天前
Binder驱动缓冲区的工作机制答疑
android
真夜1 天前
关于rngh手势与Slider组件手势与事件冲突解决问题记录
android·javascript·app