Kotlin 2.1.0 入门教程(十一)for、while、return、break、continue

devtools/2025/2/11 22:40:56/

for 循环

for 循环会遍历任何提供迭代器的对象。

kotlin">for (item in collection) print(item)for (int: Int in ints) {println(int)
}

for 循环会遍历任何提供迭代器的对象,这意味着该对象必须满足以下条件:

  • 具有一个成员函数或扩展函数 iterator(),该函数返回一个 Iterator<> 对象,而该对象:

    • 具有一个成员函数或扩展函数 next()

    • 具有一个成员函数或扩展函数 hasNext(),该函数返回一个 Boolean

  • 这三个函数都需要被标记为 operator

要遍历一个数字范围,可以使用范围表达式。

kotlin">for (i in 1..3) {print(i)
}for (i in 6 downTo 0 step 2) {print(i)
}

对于范围或数组的 for 循环会被编译成基于索引的循环,而不会创建迭代器对象。

如果你想要通过索引遍历数组或列表,可以这样操作:

kotlin">for (i in array.indices) {print(array[i])
}

或者,你可以使用 withIndex() 库函数。

kotlin">for ((index, value) in array.withIndex()) {println("the element at $index is $value")
}

while 循环

whiledo-while 循环会在条件满足的情况下持续执行其主体。

它们之间的区别在于条件检查的时机:

  • while 循环会先检查条件,如果条件满足,则执行主体,然后返回检查条件。

  • do-while 循环会先执行主体,然后才检查条件。如果条件满足,则循环重复执行。因此,do-while 的主体至少会执行一次,无论条件是否满足。

kotlin">while (x > 0) {x--
}do {val y = retrieveData()
} while (y != null) // y 在这里是可以访问的。

在循环中,Kotlin 支持传统的 breakcontinue 操作符。

返回和跳转

Kotlin 提供了三种结构化跳转表达式:

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

  • break:会终止最近的封闭循环。

  • continue:会跳过当前循环的当前迭代,继续执行下一次迭代。

kotlin">fun example() {for (i in 1..10) {if (i == 5) {return // 从函数 example 中返回。}println(i)}
}
kotlin">fun example() {for (i in 1..10) {if (i == 5) {break // 终止最近的循环。}println(i)}
}
kotlin">fun example() {for (i in 1..10) {if (i == 5) {continue // 跳过当前迭代,继续下一次迭代。}println(i)}
}

return 的作用范围:

  • 在匿名函数(如 fun 声明的函数)中,return 会从该函数返回。

  • Lambda 表达式中,return 会从最近的封闭函数返回,而不是从 Lambda 表达式返回。如果需要从 Lambda 表达式返回,可以使用标签。

breakcontinue 的作用范围:

  • breakcontinue 只能用于循环结构(如 forwhiledo-while)。

  • 如果需要从嵌套循环中跳出,可以使用标签。

如果需要从嵌套循环中跳出,或者从 Lambda 表达式中返回,可以使用标签。例如:

kotlin">loop@ for (i in 1..3) {for (j in 1..3) {if (i == 2 && j == 2) {break@loop // 从带有标签的外层循环中跳出。}println("i = $i, j = $j")}
}

所有这些表达式都可以作为更大表达式的一部分使用:

kotlin">val s = person.name ?: return

这些表达式的类型是 Nothing 类型。

Nothing 类型是 Kotlin 中的一个特殊类型,表示《无值》。它是一个不可实例化的类型,表示代码不会返回任何值,通常用于表示程序的退出点(如 returnthrow 等)。

在上面的例子中:

  • person.name 是一个可能为 null 的表达式。

  • ?:Kotlin 的空合并运算符(Elvis 运算符),用于提供一个默认值,当左侧表达式为 null 时,返回右侧的值。

  • 如果 person.name 不为 null,则 s 将被赋值为 person.name

  • 如果 person.namenull,则执行 return,表示从当前函数返回。

  • 由于 return 是一个跳转表达式,它不会返回任何值,因此它的类型是 Nothing。这意味着 val s = person.name ?: return 这行代码在 person.namenull 时,会直接从函数返回,而不会继续执行后续代码。

带标签的 breakcontinue

Kotlin 中,任何表达式都可以被标记上一个标签。

标签的格式是一个标识符后跟一个 @ 符号,例如 abc@fooBar@

要给一个表达式加上标签,只需在它前面添加一个标签即可。

kotlin">fun main() {/*i = 1, j = 11i = 1, j = 12i = 1, j = 13i = 1, j = 14i = 1, j = 15i = 2, j = 11i = 2, j = 12*/loop@ for (i in 1..5) {for (j in 11..15) {if (i == 2 && j == 13) {break@loop}println("i = $i, j = $j")}}
}
kotlin">fun main() {/*i = 1, j = 11i = 1, j = 12i = 1, j = 13i = 1, j = 14i = 1, j = 15i = 2, j = 11i = 2, j = 12i = 3, j = 11i = 3, j = 12i = 3, j = 13i = 3, j = 14i = 3, j = 15i = 4, j = 11i = 4, j = 12i = 4, j = 13i = 4, j = 14i = 4, j = 15i = 5, j = 11i = 5, j = 12i = 5, j = 13i = 5, j = 14i = 5, j = 15*/loop@ for (i in 1..5) {for (j in 11..15) {if (i == 2 && j == 13) {continue@loop}println("i = $i, j = $j")}}
}

在某些情况下,你可以在没有显式定义标签的情况下,非本地地(non-locally)使用 breakcontinue。这种非本地的用法在嵌套的内联函数中使用的 Lambda 表达式中是有效的。

breakcontinue 通常只能在它们所在的循环中使用。然而,在某些特定的上下文中,它们可以跨越多个作用域进行跳转,这种行为被称为《非本地跳转》。

当一个 Lambda 表达式被传递给一个内联函数(inline 函数)时,breakcontinue 可以在 Lambda 表达式中使用,而它们的作用范围会扩展到内联函数的调用点。这意味着你可以从 Lambda 表达式中跳转到外层的循环。

kotlin">inline fun processList(list: List<Int>, action: (Int) -> Unit) {for (item in list) {action(item)}
}fun main() {val numbers = listOf(1, 2, 3, 4, 5)processList(numbers) { number ->if (number == 3) {break // 非本地 break,跳出 processList 的循环。}println(number)}
}

这种非本地跳转允许你从 Lambda 表达式中直接跳出外层的循环。

只有在内联函数中使用的 Lambda 表达式才支持非本地跳转。这是因为内联函数会将 Lambda 表达式直接插入到调用点,从而允许跳转到外层的作用域。

带标签的 return

函数可以通过函数字面量、局部函数和对象表达式进行嵌套。带标签的 return 允许你从外层函数返回。

最重要的用例是从 Lambda 表达式中返回。要从 Lambda 表达式返回,需要给 Lambda 表达式加上标签,并使用带标签的 return

kotlin">fun main() {fun foo() {listOf(1, 2, 3, 4, 5).forEach lit@ {if (it == 3) return@litprint(it)}}foo() // 1245
}

现在,它只从 Lambda 表达式返回。

通常,使用隐式标签会更加方便,因为这种标签的名称与 Lambda 表达式所传递到的函数名称相同。

kotlin">fun main() {fun foo() {listOf(1, 2, 3, 4, 5).forEach {if (it == 3) return@forEachprint(it)}}foo() // 1245
}

或者,你可以将 Lambda 表达式替换为匿名函数。在匿名函数中,return 语句将从匿名函数本身返回。

kotlin">fun main() {fun foo() {listOf(1, 2, 3, 4, 5).forEach(fun (v: Int) {if (v == 3) returnprint(v)})}foo() // 1245
}

请注意,在前面的三个例子中,本地返回的使用与在普通循环中使用 continue 是类似的。

虽然没有直接等价于 break 的功能,但可以通过添加一个嵌套的 Lambda 表达式,并从其中非本地返回来模拟 break 的行为。

kotlin">fun main() {// 12run loop@ {listOf(1, 2, 3, 4, 5).forEach {if (it == 3) return@loopprint(it)}}
}
kotlin">fun main() {// 12run loop@ {listOf(1, 2, 3, 4, 5).forEach(fun (v: Int) {if (v == 3) return@loopprint(v)})}
}

当返回一个值时,解析器会优先考虑带标签的返回:

kotlin">return@a 1

它是:在标签 @a 处返回值 1。而不是:返回一个带标签的表达式 @a 1

在某些情况下,你可以在不使用标签的情况下从 Lambda 表达式返回。这种非本地返回位于 Lambda 表达式中,但会退出封闭的内联函数。


http://www.ppmy.cn/devtools/158045.html

相关文章

Excel 融合 deepseek

效果展示 代码实现 Function QhBaiDuYunAIReq(question, _Optional Authorization "Bearer ", _Optional Qhurl "https://qianfan.baidubce.com/v2/chat/completions")Dim XMLHTTP As ObjectDim url As Stringurl Qhurl 这里替换为你实际的URLDim postD…

Java入门 - 循环结构进阶

第1关&#xff1a;for循环的进阶使用-嵌套循环&#xff08;1&#xff09; package step1;public class ForPractice1 {public static void test() {/*****start*****/for(int i 1; i < 10; i){for(int j 1; j < 9; j)System.out.print("*");System.out.prin…

什么是推理大模型?DeepSeek R1推理大模型与DeepSeek V3模型的区别是什么?什么时候该使用推理大模型?

本文原文来自DataLearnerAI官方博客&#xff1a;什么是推理大模型&#xff1f;DeepSeek R1推理大模型与DeepSeek V3模型的区别是什么&#xff1f;什么时候该使用推理大模型&#xff1f; | 数据学习者官方网站(Datalearner) 原文较为详细&#xff0c;本文为精简版本&#xff0c;…

《从0到1CTFer成长之路》逆向工程个人笔记--逆向工程基础

可执行文件 windows 使用的是 PE 可执行文件 由 DOS 头&#xff0c;PE 文件头&#xff0c;节表及各节数据组成如果需要引用外部的动态链接库&#xff0c;则有导入表如果自己可以提供函数给其他程序来动态链接&#xff08;DLL 文件&#xff09;&#xff0c;则有导出表 Linux …

基于 Nginx 的 CDN 基础实现

概览 本文是对基于Nginx的CDN网络的学习笔记&#xff0c;阅读的代码为&#xff1a;https://github.com/leandromoreira/cdn-up-and-running 其中&#xff0c;先确定CDN中的一些基础概念&#xff1a; Balancer&#xff1a;负载均衡&#xff0c;即请求数据的流量最开始打到Bal…

windows server独立部署Qwen2.5-vl-7B

服务器配置信息 CPU&#xff1a;64G GPU&#xff1a;48G&#xff08;RTX 4090&#xff09; 一、使用conda下载模型 Qwen2.5-VL-7B-Instruct conda下载 conda create --name qwen python3.11 conda activate qwen 魔塔社区下载模型 pip install modelscope modelscope downl…

课题推荐——基于大数据预测的水面舰艇惯性/星敏感器抗干扰组合导航方法研究

在水面舰艇导航中&#xff0c;星敏感器作为一种重要的高精度定位设备&#xff0c;因其受环境因素&#xff08;如海面风浪、云层等&#xff09;影响而导致测量精度下降&#xff0c;尤其是在载体变化和观星高度变化的情况下&#xff0c;星敏感器的性能受到显著影响。这使得其无法…

Git 分布式版本控制工具使用教程

1.关于Git 1.1 什么是Git Git是一款免费、开源的分布式版本控制工具&#xff0c;由Linux创始人Linus Torvalds于2005年开发。它被设计用来处理从很小到非常大的项目&#xff0c;速度和效率都非常高。Git允许多个开发者几乎同时处理同一个项目而不会互相干扰&#xff0c;并且在…