Kotlin学习第 3 课:Kotlin 流程控制:掌握逻辑分支与循环的艺术

流程控制是编程语言的核心能力,它让程序能够根据不同条件执行不同逻辑,或重复执行特定操作。Kotlin 提供了简洁而强大的流程控制语法,在吸收 Java 优点的同时,增加了更多灵活性和表达力。本文将详细讲解 Kotlin 中的流程控制结构,帮助你掌握代码的逻辑分支与循环技巧。

一、if-else 表达式:灵活的条件判断

Kotlin 中的 if-else 不仅是流程控制语句,更是可以返回值的表达式,这比 Java 的 if-else 功能更丰富。

1. 基础用法:条件判断与分支执行

if-else 的基础用法与 Java 类似,用于根据条件执行不同代码块:

Kotlin 复制代码
fun checkNumber(num: Int) {
    if (num > 0) {
        println("正数")
    } else if (num < 0) {
        println("负数")
    } else {
        println("零")
    }
}
  • 条件表达式必须返回布尔值(Boolean
  • 当代码块只有一行时,可省略大括号(但建议保留以提高可读性)
  • else if 可用于处理多个条件分支
  • else 是可选的,用于处理所有未覆盖的情况

2. 作为表达式返回值:替代 Java 的三元运算符

Kotlin 没有 Java 中的三元运算符(condition ? a : b),因为 if-else 本身就可以作为表达式返回值:

Kotlin 复制代码
    var a = 20
    var b = 25
    var score = 80
    // 基础用法:给变量赋值
    val max = if (a > b) a else b
    println(max)

    // 复杂用法:代码块中最后一行作为返回值
    val result = if (score >= 60) {
        println("及格")
        true  // 此行为返回值
    } else {
        println("不及格")
        false // 此行为返回值
    }

这种特性让代码更灵活,尤其适合需要在条件判断中执行额外逻辑的场景。

3. 嵌套 if-else 的优化技巧

过多的嵌套 if-else 会导致代码可读性下降,可采用以下优化技巧:

技巧 1:提前返回减少嵌套

Kotlin 复制代码
// 优化前:多层嵌套
fun calculatePrice(price: Double, isMember: Boolean, isVIP: Boolean): Double {
    if (isMember) {
        if (isVIP) {
            return price * 0.7
        } else {
            return price * 0.9
        }
    } else {
        return price
    }
}

// 优化后:提前返回
fun calculatePrice(price: Double, isMember: Boolean, isVIP: Boolean): Double {
    if (!isMember) return price
    if (isVIP) return price * 0.7
    return price * 0.9
}

技巧 2:使用逻辑运算符合并条件

Kotlin 复制代码
// 优化前
if (a > 0) {
    if (b < 10) {
        // 执行逻辑
    }
}

// 优化后
if (a > 0 && b < 10) {
    // 执行逻辑
}

技巧 3:复杂场景改用 when 表达式

当条件判断过于复杂时,可考虑使用 when 表达式(下文将详细讲解)。


二、when 表达式:更强大的分支选择

when 表达式是 Kotlin 对 Java switch-case 的增强替代,支持更丰富的匹配模式,且同样可以作为表达式返回值。

1. 基础语法:替代 Java 的 switch-case

Kotlin 复制代码
fun getColorName(colorCode: Int): String {
    return when (colorCode) {
        1 -> "红色"
        2 -> "绿色"
        3 -> "蓝色"
        else -> "未知颜色"
    }
}

与 Java switch 的区别:

  • 不需要显式添加 break,默认自动跳出
  • 支持任意类型匹配(不仅是整数)
  • 必须覆盖所有可能情况(或使用 else 兜底)
  • 可作为表达式返回值

2. 匹配常量(数值、字符串、字符)

when 支持匹配各种常量类型:

Kotlin 复制代码
fun handleCommand(command: String) {
    when (command) {
        "start" -> println("启动程序")
        "stop" -> println("停止程序")
        "restart" -> println("重启程序")
        else -> println("未知命令: $command")
    }
}

fun checkChar(c: Char) {
    when (c) {
        'a', 'e', 'i', 'o', 'u' -> println("元音字母")
        in '0'..'9' -> println("数字字符")
        else -> println("其他字符")
    }
}

注意:多个常量可放在同一分支,用逗号分隔。

3. 匹配范围(in 关键字)

使用 in 关键字可匹配范围,配合 .. 区间运算符使用:

Kotlin 复制代码
fun getGrade(score: Int): Char {
    return when (score) {
        in 90..100 -> 'A'
        in 80 until 90 -> 'B'  // until 表示半开区间 [80,90)
        in 60 until 80 -> 'C'
        in 0 until 60 -> 'D'
        else -> '?'
    }
}

in 还可用于检查是否在集合中:

Kotlin 复制代码
fun isValidOperator(op: String): Boolean {
    return when (op) {
        in setOf("+", "-", "*", "/") -> true
        else -> false
    }
}

4. 匹配类型(is 关键字)

使用 is 关键字可进行类型判断,且会自动完成类型转换(智能转换):

Kotlin 复制代码
fun handleData(data: Any) {
    when (data) {
        is String -> println("字符串长度: ${data.length}")  // 自动转换为 String
        is Int -> println("整数的平方: ${data * data}")     // 自动转换为 Int
        is Boolean -> println("布尔值: $data")
        else -> println("未知类型: ${data.javaClass.name}")
    }
}

这比 Java 的 instanceof 更简洁,无需显式类型转换。

5. 作为表达式使用

when 作为表达式时,符合条件的分支值即为返回值:

Kotlin 复制代码
fun calculate(a: Int, b: Int, op: String): Int {
    return when (op) {
        "+" -> a + b
        "-" -> a - b
        "*" -> a * b
        "/" -> if (b != 0) a / b else 0
        else -> throw IllegalArgumentException("不支持的运算符: $op")
    }
}

甚至可以不带参数,直接在分支条件中写任意布尔表达式:

Kotlin 复制代码
fun checkNumber(n: Int): String {
    return when {
        n > 0 && n % 2 == 0 -> "正偶数"
        n > 0 && n % 2 == 1 -> "正奇数"
        n < 0 -> "负数"
        else -> "零"
    }
}

三、for 循环:简洁的迭代方式

Kotlin 的 for 循环主要用于遍历迭代器(如区间、集合、数组等),语法比 Java 更简洁。

1. 遍历区间(.. 运算符、until、step)

Kotlin 提供了直观的区间表示法,配合 for 循环可轻松实现次数控制:

Kotlin 复制代码
// 闭区间 [1,5]:包含 1 和 5
for (i in 1..5) {
    print(i)  // 输出:12345
}

// 半开区间 [1,5):包含 1,不包含 5
for (i in 1 until 5) {
    print(i)  // 输出:1234
}

// 倒序遍历
for (i in 5 downTo 1) {
    print(i)  // 输出:54321
}

// 指定步长(step)
for (i in 1..10 step 2) {
    print(i)  // 输出:13579
}

// 倒序+步长
for (i in 10 downTo 2 step 2) {
    print(i)  // 输出:108642
}

2. 遍历集合(List/Set/Map)

Kotlin 对集合的遍历支持非常友好:

Kotlin 复制代码
// 遍历 List
val fruits = listOf("苹果", "香蕉", "橙子")
for (fruit in fruits) {
    println(fruit)
}

// 遍历 Set
val numbers = setOf(10, 20, 30)
for (num in numbers) {
    println(num)
}

// 遍历 Map
val user = mapOf(
    "name" to "张三",
    "age" to 25,
    "gender" to "男"
)

// 方式1:遍历键值对
for ((key, value) in user) {
    println("$key: $value")
}

// 方式2:遍历键
for (key in user.keys) {
    println("键: $key")
}

// 方式3:遍历值
for (value in user.values) {
    println("值: $value")
}

3. 遍历数组

数组遍历与集合类似,还可通过索引遍历:

Kotlin 复制代码
val arr = arrayOf("a", "b", "c", "d")

// 直接遍历元素
for (item in arr) {
    println(item)
}

// 通过索引遍历
for (i in arr.indices) {  // indices 返回数组索引范围
    println("索引 $i: ${arr[i]}")
}

// 同时获取索引和元素
for ((index, value) in arr.withIndex()) {
    println("索引 $index: $value")
}

4. 自定义循环次数与步长

结合区间操作符,可灵活控制循环次数和步长:

Kotlin 复制代码
// 循环 5 次(0-4)
for (i in 0 until 5) {
    println("循环第 ${i+1} 次")
}

// 从 10 循环到 1,步长为 3
for (i in 10 downTo 1 step 3) {
    println(i)  // 输出:10 7 4 1
}

四、while 与 do-while 循环:条件控制的循环

whiledo-while 循环适用于需要根据条件重复执行的场景,两者的区别在于执行顺序不同。

1. while 循环:先判断后执行

while 循环先判断条件,只有条件为 true 时才执行循环体:

Kotlin 复制代码
fun countDown(n: Int) {
    var remaining = n
    while (remaining > 0) {  // 先判断条件
        println(remaining)
        remaining--
    }
    println("发射!")
}

// 调用:countDown(3) 
// 输出:3 2 1 发射!

如果初始条件就为 false,循环体一次也不会执行。

2. do-while 循环:先执行后判断

do-while 循环先执行一次循环体,再判断条件,因此至少会执行一次:

Kotlin 复制代码
fun inputUntilPositive() {
    var number: Int
    do {
        println("请输入一个正数:")
        number = readLine()?.toIntOrNull() ?: 0
    } while (number <= 0)  // 后判断条件
    println("你输入了正数:$number")
}

适合需要 "至少执行一次" 的场景,如用户输入验证。

3. 循环终止(break)与跳过(continue)

  • break:立即终止当前循环,跳出循环体
  • continue:跳过当前循环的剩余部分,直接进入下一次循环
Kotlin 复制代码
// 使用 break 终止循环
for (i in 1..10) {
    if (i == 5) break  // 当 i=5 时终止循环
    print(i)  // 输出:1234
}

// 使用 continue 跳过当前迭代
for (i in 1..10) {
    if (i % 2 == 0) continue  // 偶数时跳过
    print(i)  // 输出:13579
}

4. 嵌套循环的使用场景

嵌套循环常用于处理多维数据结构(如二维数组)或需要多层迭代的场景:

Kotlin 复制代码
// 打印 5x5 的乘法表
for (i in 1..5) {
    for (j in 1..i) {
        print("$j×$i=${i*j} ")
    }
    println()  // 换行
}

// 输出:
// 1×1=1 
// 1×2=2 2×2=4 
// 1×3=3 2×3=6 3×3=9 
// ...

带标签的 break/continue

在嵌套循环中,可通过标签(label@)控制外层循环:

Kotlin 复制代码
outer@ for (i in 1..3) {
    inner@ for (j in 1..3) {
        if (i == 2 && j == 2) {
            break@outer  // 终止外层循环
            // continue@outer  // 跳过外层循环的当前迭代
        }
        print("($i,$j) ")
    }
    println()
}

输出(使用 break@outer 时):

plaintext 复制代码
(1,1) (1,2) (1,3) 
(2,1) 

五、流程控制的最佳实践

  1. 优先使用表达式形式if-elsewhen 作为表达式可使代码更简洁
  2. 减少嵌套层级:过多的嵌套会降低可读性,可通过提前返回、逻辑合并等方式优化
  3. 合理选择循环类型
    • 遍历区间 / 集合首选 for 循环
    • 条件循环优先考虑 while
    • 至少执行一次的场景用 do-while
  4. 避免死循环 :确保循环条件最终会变为 false,或提供明确的 break 出口
  5. 复杂条件用 when :多分支判断时,whenif-else 链更易读
相关推荐
杨杨杨大侠7 小时前
第5章:实现Spring Boot集成
java·github·eventbus
CYRUS_STUDIO7 小时前
别让 so 裸奔!移植 OLLVM 到 NDK 并集成到 Android Studio
android·android studio·llvm
华仔啊7 小时前
工作5年没碰过分布式锁,是我太菜还是公司太稳?网友:太真实了!
java·后端
尚久龙7 小时前
安卓学习 之 图片控件和图片按钮
android·java·学习·手机·android studio·安卓
摸鱼仙人~7 小时前
深入理解 MyBatis-Plus 的 `BaseMapper`
java·开发语言·mybatis
杨杨杨大侠7 小时前
第6章:高级特性与性能优化
java·github·eventbus
东风西巷7 小时前
Don‘t Sleep:保持电脑唤醒,确保任务不间断
android·电脑·软件需求
Dcs7 小时前
代码评审还能更好!
java
tangweiguo030519877 小时前
FlutterActivity vs FlutterFragmentActivity:全面对比与最佳实践
android·flutter