Skip to content

控制流与区间 (Control Flow)

源:Kotlin 控制流指南

Kotlin 的控制流设计倾向于 表达式 (Expression) 而非 语句 (Statement)。这意味着大部分控制结构(如 if, try, when)都有返回值,从而消除了对三元运算符的需求。

If 表达式

if 在 Kotlin 中是表达式,可以直接赋值。

kotlin
// 1. 替代三元运算符
val max = if (a > b) a else b

// 2. 代码块形式 (最后一行是返回值)
val state = if (isConnected) {
    println("Connected")
    "Online"
} else {
    println("Offline")
    "Offline" // 必须有 else 分支,否则无法推导返回值类型
}

When 表达式 (超级 Switch)

when 是 Kotlin 中最强力的控制结构。它既可以替代 switch-case,也可以替代复杂的 if-else 链。

kotlin
when (x) {
    1 -> print("x == 1")
    2, 3 -> print("x is 2 or 3") // 组合匹配
    in 1..10 -> print("x is in range") // 区间匹配
    !in 10..20 -> print("x is outside range")
    is String -> print(x.length) // 类型匹配与智能转换
    else -> print("Unknown")
}
kotlin
// 替代 if (a) ... else if (b) ...
when {
    x.isOdd() -> print("x is odd")
    y.isEven() -> print("y is even")
    else -> print("neither")
}
kotlin
// 在表达式中直接声明变量 (Kotlin 1.3+)
// response 仅在 when 块内可见,污染最小化
when (val response = executeRequest()) {
    is Success -> showData(response.body)
    is Error -> showError(response.msg)
}

核心特性:穷举性检查 (Exhaustiveness)

对于 密封类 (Sealed Classes)密封接口 (Sealed Interfaces)枚举 (Enums)when 表达式强制要求覆盖所有情况。这在 Android MVI 架构中处理 UI State 时至关重要。

kotlin
sealed interface UiState
data object Loading : UiState
data class Success(val data: String) : UiState
data class Error(val msg: String) : UiState

fun render(state: UiState) {
    // 编译器会报错:'when' expression must be exhaustive
    // 强制你处理所有状态,避免遗漏
    val text = when (state) {
        Loading -> "Loading..."
        is Success -> state.data
        is Error -> state.msg
    }
}

循环与区间 (Loops & Ranges)

区间表达式

Kotlin 提供了直观的区间操作符。

kotlin
// 包含 1 和 10
for (i in 1..10)
kotlin
// 包含 1,不包含 10 (1 <= i < 10)
// 常用于数组遍历
for (i in 1 until 10)
kotlin
// 10, 9, ..., 1
for (i in 10 downTo 1)
kotlin
// 1, 3, 5, 7, 9
for (i in 1..10 step 2)

增强型 For 循环

kotlin
val list = listOf("A", "B", "C")

// 1. 同时获取索引与值
for ((index, value) in list.withIndex()) {
    println("Item at $index is $value")
}

// 2. 替代 for 循环的高阶函数 (更函数式)
repeat(5) { i ->
    println("Execution #$i")
}

结构化跳转 (Jumps)

标签 (Labels)

标签允许我们控制 breakcontinuereturn 的目标范围。格式为 labelName@

kotlin
// 跳出多层循环
outerLoop@ for (i in 1..10) {
    for (j in 1..10) {
        if (i * j > 50) {
            // 直接跳出最外层的 outerLoop,而不只是内层
            break@outerLoop 
        }
    }
}
kotlin
// 从 Lambda 返回而非从函数返回
fun foo() {
    listOf(1, 2, 3).forEach {
        if (it == 2) {
             // ❌ 错误:这会直接结束 foo() 函数!
             // return 
             
             // ✅ 正确:仅结束当前 Lambda 的本次迭代 (类似 continue)
             return@forEach 
        }
        print(it)
    }
}