美文网首页
Kotlin之returns和jumps

Kotlin之returns和jumps

作者: 愿天深海 | 来源:发表于2023-06-20 11:26 被阅读0次

    最近遇到在循环中达到某个条件之后需要退出循环的需要,在Kotlin的foreach中使用return@forEach竟然有坑,因此特地写下该篇文章记录下来。

    在Kotlin的foreach中使用return@forEach是类似continue的效果,跳转至循环的下一步,如果要跳出循环,需要在循环外面标记run loop@{},然后使用return@loop跳出循环。

    进入正文

    跳转

    Kotlin中有三种可以达到跳转目的的方式:

    • return:默认情况下,从最近的闭合函数或者匿名函数返回。
    • break:默认情况下,终止最近的闭合循环。
    • continue:默认情况下,前进到最近的闭合循环的下一步。

    所有这些表达式都可以用作更大表达式的一部分,例如

    val s = person.name ?: return
    

    标签

    Kotlin中任何表达式都可以使用标签来进行标记。标签的形式是标识符后跟符号@,例如abc@或fooBar@。要标记表达式,只需在其前面添加一个标签即可。

    loop@ for (i in 1..100) {
        // ...
    }
    

    break

    break:默认情况下,终止最近的闭合循环。

    示例:

    for (i in 1..5) {
        for (j in 1..5) {
            if (j == 3) break
            Log.d("loop", "i:${i},j:${j}")
        }
    }
    

    输出结果:

    i:1,j:1
    i:1,j:2
    i:2,j:1
    i:2,j:2
    i:3,j:1
    i:3,j:2
    i:4,j:1
    i:4,j:2
    i:5,j:1
    i:5,j:2
    

    可以看到,break终止了最近的j循环,如果想要直接跳出外部的i循环,就可以使用标签来限定。

    示例:

    loop@ for (i in 1..5) {
        for (j in 1..5) {
            if (j == 3) break@loop
            Log.d("loop", "i:${i},j:${j}")
        }
    }
    

    输出结果:

    i:1,j:1
    i:1,j:2
    

    continue

    continue:默认情况下,前进到最近的闭合循环的下一步。

    示例:

    for (i in 1..5) {
        for (j in 1..5) {
            if (j == 3) continue
            Log.d("loop", "i:${i},j:${j}")
        }
    }
    

    输出结果:

    i:1,j:1
    i:1,j:2
    i:1,j:4
    i:1,j:5
    i:2,j:1
    i:2,j:2
    i:2,j:4
    i:2,j:5
    i:3,j:1
    i:3,j:2
    i:3,j:4
    i:3,j:5
    i:4,j:1
    i:4,j:2
    i:4,j:4
    i:4,j:5
    i:5,j:1
    i:5,j:2
    i:5,j:4
    i:5,j:5
    

    可以看到,continue在最近的j循环中,跳过了3,前进到了4,如果使用标签来限定。

    示例:

    loop@ for (i in 1..5) {
        for (j in 1..5) {
            if (j == 3) continue@loop
            Log.d("loop", "i:${i},j:${j}")
        }
    }
    

    输出结果:

    i:1,j:1
    i:1,j:2
    i:2,j:1
    i:2,j:2
    i:3,j:1
    i:3,j:2
    i:4,j:1
    i:4,j:2
    i:5,j:1
    i:5,j:2
    

    每次执行到j=3时,continue是跳过i循环当前步的接下去操作,然后前进到i循环的下一步,可以发现i循环的continue效果等同于上面的j循环的break效果。

    return

    默认情况下,从最近的闭合函数或者匿名函数返回。

    示例:

    repeat(5) {
        if (it == 2) return@repeat
        Log.d("loop", "repeat:${it}")
    }
    

    输出结果:

    repeat:0
    repeat:1
    repeat:3
    repeat:4
    

    示例:

    listOf(1, 2, 3, 4, 5).forEach {
        if (it == 3) return@forEach
        Log.d("loop", "forEach:${it}")
    }
    

    输出结果:

    forEach:1
    forEach:2
    forEach:4
    forEach:5
    

    可以看到return@repeat没有退出当前repeat函数,return@forEach也没有退出当前forEach函数,整个就是一个continue效果。
    进去看一下源码:

    /**
     * Executes the given function [action] specified number of [times].
     *
     * A zero-based index of current iteration is passed as a parameter to [action].
     *
     * @sample samples.misc.ControlFlow.repeat
     */
    @kotlin.internal.InlineOnly
    public inline fun repeat(times: Int, action: (Int) -> Unit) {
        contract { callsInPlace(action) }
    
        for (index in 0 until times) {
            action(index)
        }
    }
    
    /**
     * Performs the given [action] on each element.
     */
    @kotlin.internal.HidesMembers
    public inline fun <T> Iterable<T>.forEach(action: (T) -> Unit): Unit {
        for (element in this) action(element)
    }
    

    发现了什么,lambda表达式,内联函数,高阶函数。
    可以在最下方参考文献 Kotlin的文档上找到非常明确的解释。
    如果直接使用return,会直接结束当前的整个函数,自然是不行。
    可如果是使用隐式标签,@repeat和@forEach,这样的标签和传递过来的lambda表达式函数同名,所以return@repeat和return@forEach的意思也就是结束lambda表达式函数,而这仅仅只是其中一次遍历过程,所以效果等同于continue效果。
    如果想要达到break的效果,就需要在外面再套一层并进行标记。

    示例:

    run loop@{
        repeat(5) {
            if (it == 2) return@loop
            Log.d("loop", "repeat:${it}")
        }
    }
    

    输出结果:

    repeat:0
    repeat:1
    

    示例:

    run loop@{
        listOf(1, 2, 3, 4, 5).forEach {
            if (it == 3) return@loop
            Log.d("loop", "forEach:${it}")
        }
    }
    

    输出结果:

    forEach:1
    forEach:2
    

    参考文献:https://kotlinlang.org/docs/returns.html

    相关文章

      网友评论

          本文标题:Kotlin之returns和jumps

          本文链接:https://www.haomeiwen.com/subject/ubpeydtx.html