控制流:程序执行的“交通指挥员”

各位同学,欢迎来到 Kotlin 控制流的世界。说实话,控制流是编程语言中最基础、也最核心的部分。它决定了你的代码怎么走、往哪走、什么时候停。我刚开始学编程时,总觉得控制流很简单,不就是 if-else 嘛。但后来在项目中踩过不少坑,才发现这里面门道还挺多。

今天我们就来聊聊 Kotlin 中的控制流。Kotlin 在这方面做得相当优雅,尤其是 when 表达式,比 Java 的 switch 强太多了。你想想看,一个表达式能返回值,还能做类型匹配,这多方便。

核心要点:Kotlin 的控制流不仅仅是语句,很多都是表达式——它们可以返回值。这是 Kotlin 区别于 Java 的一个重要特性。

Kotlin 控制流知识体系 控制流 条件判断 if 表达式 when 表达式 循环 for 循环 while 循环 控制关键字 break / continue 范围表达式 (Range) Kotlin 控制流:表达式优先,简洁安全

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