简单记录一下Kotlin中标签(Lable)的使用,以及相关
正文
什么是标签
标签 = 给表达式 / 循环 / Lambda 起个名字,用来精确控制 jump
val intArray = intArrayOf(1, 2, 3, 4, 5) intArray.forEach here@ { if (it == 3) return@here println(it) }
这里的 here@就是标签。
当it==3时,跳出循环。
输出结果
1 2 4 5
再来看一个例子
val intArray = intArrayOf(1, 2, 3, 4, 5) intArray.forEach { if (it == 3) return@forEach //返回@forEach 处继续下一个循环 println(it) }
输出结果:
1 2 4 5
任何表达式都可以用标签标记
任何表达式都可以用标签标记
包括:
| 可标记对象 | 示例 |
|---|---|
| for / while | loop@ for (...) {} |
| if / when | check@ if (...) {} |
| Lambda | run label@ { ... } |
| 任意表达式 | label@ { 1 + 2 } |
val result = label@ { 1 + 2 }
Label 的三大用途
控制break / continue
跳出多层循环
outer@ for (i in 1..3) { inner@ for (j in 1..3) { if (i == 2 && j == 2) break@outer println("$i $j") } }
输出:
1 1 1 2 1 3 2 1
控制return
这是标签最有价值的地方。
没有 label(错误直觉)
fun test() { listOf(1, 2, 3).forEach { if (it == 2) return // ❌ 直接 return test() println(it) } }
输出:
1很多人以为只跳出 Lambda,其实是 return 整个函数
上面直接退出了test()
用label精确 return
fun test() { listOf(1, 2, 3).forEach label@{ if (it == 2) return@label println(it) } println("done") }
输出:
13done
只跳出 Lambda,不跳出函数
隐式标签
Kotlin 会自动给 Lambda 所在的函数 / 表达式 生成标签:
listOf(1, 2, 3).forEach { if (it == 2) return@forEach println(it) }
这里的 forEach就是隐式标签。
Label + 高阶函数
结合你之前问的 () -> Unit/ 高阶函数:
fun runBlock(block: () -> Unit) { block() } fun test() { runBlock { println("start") return@runBlock println("end") // 不会执行 } }
这里的 return@runBlock是跳出一个函数参数
常见误区
1. Label 不是“goto”
label@ { return@label // ✅ 只能跳转到 label 所在的表达式结束 }
Kotlin 不支持 Java 那种 goto
2. Label 不能跨函数
fun a() { run label@{ b() } } fun b() { return@label // ❌ 编译错误 }
3. Label 不影响返回值类型
val f = label@ { 1 + 2 } // 类型仍然是 () -> Int
什么时候该用 Label?
| 场景 | 是否推荐 |
|---|---|
| 跳出多层 for | ✅ 必须用 |
| Lambda 中 return | ✅ 推荐 |
| DSL(Anko / Compose) | ✅ 非常常见 |
| 普通 if / when | ❌ 没必要 |
| 想“goto” | ❌ 禁止 |
总结
Label 不是给“表达式起名”,而是给“控制流一个出口”
它最重要的价值:在 Lambda 里 return 到“你想停的地方

