文章

Kotlin return@xxx 的坑

Kotlin Return 到标签

先看例子:

1
2
3
4
5
6
7
(1..5).forEach {
    if (it == 3) {
        return@forEach
    }
    println(it)
}
println("test over")

这段代码执行结果是什么?

错误:

1
2
3
1
2
test over

这里可千万不要想当然,认为循环会结束。正确的结果是

1
2
3
4
5
1
2
4
5
test over

关于 Kotlin 中 return 使用的官方文档: https://www.kotlincn.net/docs/reference/returns.html

先说结论:

1. return 默认从最直接包围它的函数或者匿名函数返回。 2. return 后面跟标签,返回到标签。

关于第一点,如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
fun test() {
    (1..5).forEach {
        if (it == 3) {
            return
        }
        println(it)
    }
    println("test over")
}
``

此时 return 会直接从 test() 函数中返回,输出:

1 2

1
2
3
4
5
6
7
对于第二点,返回到标签,首先名明白什么是标签。在 Kotlin 中任何表达式都可以用标签来标记,标签的格式为标识符后面跟@ 符号,例如 `abc@`、`aaa@` 等都是有效标识符。

再看开头的例子,为什么没有跳出循环?

其实例子中 `@forEach` 是一个和隐式标签,该例子等价于:

(1..5).forEach xxx@{ if (it == 3) { return@xxx // 返回到 lambda 表达式的调用者 } println(it) } println(“test over”)

1
2
3
4
5
forEach 后面跟的式一个lambda 表达式,此时的 return 实际上是返回到该 lambda 表达式的调用者,而并跳出 forEach 循环。

等价于下面使用匿名函数的实现方式,代码如下:

(1..5).forEach(fun(value: Int) { if (value == 3) return // 返回到匿名函数的调用者 println(value) }) println(“test over”)

1
2
3
4
5
那如果想要在循环到 3 的时候跳出循环,而不跳出函数,该如何办呢?

我们需要再调用 forEach 循环的调用处添加一个标签,再返回到该标签即可。如下:

run www@{ (1..5).forEach { if (it == 3) { return@www } println(it) } println(“test over”) } ```

知识点虽小,但是本人真真切切地踩过坑。记录下来,也希望其他人忽视了这个知识点的人,看到以后不要踩坑了。。。

文章可转载,转载请务必注明出处。