控制流:程序执行的“交通指挥员”
各位同学,欢迎来到 Kotlin 控制流的世界。说实话,控制流是编程语言中最基础、也最核心的部分。它决定了你的代码怎么走、往哪走、什么时候停。我刚开始学编程时,总觉得控制流很简单,不就是 if-else 嘛。但后来在项目中踩过不少坑,才发现这里面门道还挺多。
今天我们就来聊聊 Kotlin 中的控制流。Kotlin 在这方面做得相当优雅,尤其是 when 表达式,比 Java 的 switch 强太多了。你想想看,一个表达式能返回值,还能做类型匹配,这多方便。
核心要点:Kotlin 的控制流不仅仅是语句,很多都是表达式——它们可以返回值。这是 Kotlin 区别于 Java 的一个重要特性。
if 表达式:不只是判断,还能赋值
在 Java 中,if 是语句。在 Kotlin 中,if 是表达式。这意味着什么?意味着你可以把 if 的结果直接赋给一个变量。我个人特别喜欢这个特性,它让代码变得非常简洁。
// Java 风格(Kotlin 也支持)
var max = a
if (a < b) {
max = b
}
// Kotlin 推荐风格——if 作为表达式
val max = if (a < b) b else a
// 甚至可以写多行
val result = if (score >= 90) {
println("优秀")
"A"
} else if (score >= 80) {
println("良好")
"B"
} else {
println("继续努力")
"C"
}
我的习惯:如果 if-else 只有一行,我通常写在一行。如果分支逻辑复杂,我会用花括号包起来,并且最后一个表达式就是返回值。注意,if 作为表达式时,必须有 else 分支,否则编译器会报错。
when 表达式:switch 的全面升级
when 表达式是 Kotlin 的一大亮点。说白了,它就是 Java switch 的超级增强版。我在项目中用 when 替换了大量的 if-else 链,代码可读性提升了不少。
基本用法
val grade = when (score) {
100 -> "满分"
in 90..99 -> "优秀"
in 80..89 -> "良好"
in 70..79 -> "中等"
in 60..69 -> "及格"
else -> "不及格"
}
高级用法:类型匹配
这个功能我特别喜欢。在 Android 开发中,经常需要根据对象类型做不同处理。用 when 配合智能类型转换,代码非常优雅。
fun describe(obj: Any): String = when (obj) {
is String -> "这是一个字符串,长度是 ${obj.length}"
is Int -> "这是一个整数,值是 $obj"
is List<*> -> "这是一个列表,有 ${obj.size} 个元素"
!is String -> "这不是字符串"
else -> "未知类型"
}
我曾经踩过的坑:when 表达式如果没有覆盖所有可能的分支,并且没有 else,编译器会报错。尤其是当你用 when 作为表达式返回值时,必须保证所有情况都被覆盖。我刚开始用 Kotlin 时,经常忘记加 else,结果编译不过去。
不带参数的 when
有时候我们不需要传入参数,直接写条件判断。这种写法比 if-else 链更清晰。
when {
x.isOdd() -> println("x 是奇数")
y.isEven() -> println("y 是偶数")
else -> println("都不满足")
}
for 循环:遍历一切可迭代对象
Kotlin 的 for 循环非常灵活。它本质上是 for-each 循环,可以遍历任何实现了迭代器的对象。
// 遍历数组
val array = intArrayOf(1, 2, 3, 4, 5)
for (item in array) {
println(item)
}
// 带索引遍历
for ((index, value) in array.withIndex()) {
println("索引 $index 的值是 $value")
}
// 遍历字符串
for (char in "Kotlin") {
println(char)
}
// 遍历 Map
val map = mapOf("A" to 1, "B" to 2)
for ((key, value) in map) {
println("$key -> $value")
}
我的建议:在 Android 开发中,经常需要遍历列表。用 for 循环配合解构声明,代码会非常简洁。比如遍历 Pair 列表时,直接解构出两个值,省去了手动 get 的麻烦。
while 循环:条件驱动
while 循环和 do-while 循环与其他语言基本一致。不过 Kotlin 的 while 循环有一个特点——它不能作为表达式使用,只能作为语句。
var x = 10
while (x > 0) {
println(x)
x--
}
// do-while 至少执行一次
var y = 0
do {
println(y)
y++
} while (y < 5)
break 与 continue:循环的控制杆
这两个关键字的作用和其他语言类似。但 Kotlin 有一个很实用的特性——标签(label)。
// 不带标签的 break
for (i in 1..10) {
if (i == 5) break // 跳出当前循环
println(i)
}
// 带标签的 break——跳出外层循环
outer@ for (i in 1..3) {
for (j in 1..3) {
if (i == 2 && j == 2) break@outer
println("i=$i, j=$j")
}
}
我曾经犯过的错:在嵌套循环中使用 break 时,如果不加标签,默认只跳出内层循环。有一次我写了一个双层循环,想跳出外层,结果忘了加标签,导致逻辑错误。调试了半天才发现问题。所以,嵌套循环中如果需要跳出外层,一定要用标签。
范围表达式(Range):Kotlin 的语法糖
范围表达式是 Kotlin 的一个小甜点。它用 .. 操作符表示一个区间,配合 in 和 !in 使用,非常直观。
// 基本范围
val range = 1..10 // 包含 1 到 10
val downRange = 10 downTo 1 // 递减范围
val stepRange = 1..10 step 2 // 步长为 2
// 检查是否在范围内
if (age in 18..60) {
println("成年人")
}
// 检查是否不在范围内
if (char !in 'a'..'z') {
println("不是小写字母")
}
// 范围在 for 循环中的应用
for (i in 1..5) {
println(i)
}
// 字符范围
for (c in 'A'..'F') {
println(c)
}
我的使用习惯:在 Android 开发中,我经常用范围表达式来做条件判断。比如判断用户年龄是否在合法范围内,或者判断分数等级。它比写 a >= 18 && a <= 60 要直观得多。
综合示例:控制流实战
下面是一个综合示例,展示了控制流在实际场景中的应用。假设我们要实现一个简单的成绩管理系统。
fun evaluateStudent(name: String, scores: List<Int>) {
// 使用范围表达式检查分数是否合法
for (score in scores) {
if (score !in 0..100) {
println("$name 的分数 $score 不合法")
return
}
}
// 计算平均分
val average = scores.sum() / scores.size
// 使用 when 表达式评定等级
val grade = when (average) {
in 90..100 -> "A"
in 80..89 -> "B"
in 70..79 -> "C"
in 60..69 -> "D"
else -> "F"
}
// 使用 if 表达式判断是否通过
val passed = if (average >= 60) "通过" else "未通过"
println("$name 的平均分是 $average,等级 $grade,$passed")
}
// 测试
evaluateStudent("张三", listOf(85, 90, 78))
evaluateStudent("李四", listOf(45, 55, 60))
总结
Kotlin 的控制流设计得很用心。if 和 when 都是表达式,可以返回值,这让代码更简洁。范围表达式是 Kotlin 独有的语法糖,用起来很顺手。break 和 continue 配合标签,可以精确控制循环的跳转。
我个人觉得,Kotlin 在控制流方面的设计,体现了「表达式优先」的理念。能写成表达式的,尽量不写成语句。这样代码更函数式,也更安全。你想想看,用 val 声明不可变变量,配合表达式式的控制流,很多潜在的 bug 在编译期就被消灭了。
好了,控制流的内容就讲到这里。下一节我们会聊函数和 Lambda 表达式,那是 Kotlin 函数式编程的起点。
公众号:蓝海资料掘金营,微信deep3321