Kotlin | 在for、forEach循环中正确的使用break、continue

文章目录

Kotlin 有三种结构化跳转表达式:

  • return :默认从最直接包围它的函数或者匿名函数返回。
  • break:终止最直接包围它的循环。
  • continue:继续下一次最直接包围它的循环。

for循环中使用break、continue

kotlin 复制代码
fun forControl() {
    for (i in 1..5) {
        if (i == 3) break //1 这里分别使用break continue return
        println("i: $i")
    }
    println("循环外继续执行")
}

1处分别使用break、continue、return 替换,执行结果如下:

kotlin 复制代码
//break 
i: 1
i: 2
循环外继续执行

//continue
i: 1
i: 2
i: 4
i: 5
循环外继续执行

//return
i: 1
i: 2

嗯,跟Java中的使用姿势是一样的,继续往下看。

Label标签

在 Kotlin 中任何表达式都可以用标签(label)来标记。 标签的格式为标识符后跟 @ 符号,例如:abc@、loop@都是有效的标签。 要为一个表达式加标签,我们只要在其前加标签即可。示例:

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

这里在嵌套for循环中使用Label,可以控制break及continue的范围:

kotlin 复制代码
fun forNestedControl() {
   loop@ for (i in 1..2) {
          println("i: $i")
          for (j in 1..5) {
              if (j == 3) break@loop //break continue
              println("j: $j")
          }
      }
}

执行结果:

kotlin 复制代码
//break
i: 1
j: 1
j: 2
循环外继续执行

//continue
i: 1
j: 1
j: 2

i: 2
j: 1
j: 2
循环外继续执行

注意不能在上述代码中使用return@loop,因为目标标签表示的不是函数,错误信息如下:

Target label does not denote a function

结论:标签限制的 break 跳转到刚好位于该标签指定的循环后面的执行点。 continue 继续标签指定的循环的下一次迭代

forEach中如何退出循环

在forEach中并不能直接使用break、continue:

可以看到直接报错了,错误信息也很明确:break 和 continue 只允许在循环中使用 ,而这里是forEach的闭包,所以并不能直接使用break 和 continue。那么如何在forEach中分别模拟出break、continue的效果呢?通过Label即可实现,如:

kotlin 复制代码
fun forEachControl() {
    listOf(1, 2, 3, 4, 5).forEach forEach@{
        if (it == 3) return@forEach
        println("it:$it")
    }
    println("循环外继续执行")
}

return 只会从 lambda 表达式中返回。通常情况下使用隐式标签更方便(Label 标签与接受该 lambda 的函数同名即可使用隐式标签),简化之后:

kotlin 复制代码
fun forEachControl() {
    listOf(1, 2, 3, 4, 5).forEach{
        if (it == 3) return@forEach
        println("it:$it")
    }
    println("循环外继续执行")
}

代码执行结果:

kotlin 复制代码
it:1
it:2
it:4
it:5
循环外继续执行

可以看到return@forEach相当于表达式里面的continue了。嗯哼?为什么不是break的效果呢?明明已经return@forEach了呀,其实这是Kotlin闭包带来的副作用,看下forEach的源码:

kotlin 复制代码
public inline fun <T> Iterable<T>.forEach(action: (T) -> Unit): Unit {
    //注意看下面这行代码的逻辑
    for (element in this) action(element)
}

action闭包作为参数传入的,所以在forEach中return@forEach只能停止当前闭包的逻辑,后面的循环并不会受影响,会继续后面的循环。那么如何在forEach中模拟break的效果呢?只要把声明Label放到forEach外面即可以了:

kotlin 复制代码
fun forEachControl() {
    run loop@{
       listOf(1, 2, 3, 4, 5).forEach {
          if (it == 3) return@loop
          println("it:$it")
        }
          println("循环外继续执行")
        }
    }

执行结果:

kotlin 复制代码
it:1
it:2

资料

【1】Kotlin返回和跳转:https://www.kotlincn.net/docs/reference/returns.html

相关推荐
消失的旧时光-19432 小时前
从 Kotlin 到 Dart:为什么 sealed 是处理「多种返回结果」的最佳方式?
android·开发语言·flutter·架构·kotlin·sealed
有位神秘人2 小时前
kotlin与Java中的单例模式总结
java·单例模式·kotlin
Jinkxs2 小时前
Gradle - 与Groovy/Kotlin DSL对比 构建脚本语言选择指南
android·开发语言·kotlin
&有梦想的咸鱼&2 小时前
Kotlin委托机制的底层实现深度解析(74)
android·开发语言·kotlin
golang学习记2 小时前
IntelliJ IDEA 2025.3 重磅发布:K2 模式全面接管 Kotlin —— 告别 K1,性能飙升 40%!
java·kotlin·intellij-idea
gjxDaniel2 天前
Kotlin编程语言入门与常见问题
android·开发语言·kotlin
野生技术架构师2 天前
Java 21虚拟线程 vs Kotlin协程:高并发编程模型的终极对决与选型思考
java·开发语言·kotlin
言之。2 天前
Kotlin快速入门
android·开发语言·kotlin
常利兵2 天前
Android Gradle 构建脚本现代化:Kotlin DSL (.kts) 与 Groovy DSL 深度对比与实战指南
android·开发语言·kotlin
baidu_247438612 天前
Android kotlin 定时n秒完成时回调,含暂停和继续
android·kotlin