Kotlin: Kotlin控制流详解

最后更新:2026-08-26

Kotlin 的控制流不仅是流程控制—— 和 是表达式,有返回值,让 Charlie 的订单分流逻辑既安全又简洁。

1. 你将学到


2. 一个架构师的真实故事

(1) 痛点:嵌套 if-else 地狱

Charlie 的 Java 版 OrderProcessor 用 5 层嵌套 if-else 处理订单状态分流,120 行代码只为了判断走哪条处理流水线。新成员 Bob 加入后,3 次改错分支条件导致生产事故。

(2) Kotlin when 表达式的解法

KOTLIN
// Clean, exhaustive, compiler-verified
fun route(order: Order): Pipeline = when (order.status) {
    Status.PENDING -> PendingPipeline
    Status.CONFIRMED -> if (order.total > 10_000) VipPipeline else StandardPipeline
    Status.SHIPPED -> TrackingPipeline
    Status.CANCELLED -> RefundPipeline
}

表达式穷尽检查 + 编译器守护,分支遗漏直接报错,Bob 再也改不出 Bug。


3. if 表达式

(1) if 是表达式,有返回值

KOTLIN
// if as expression
val max = if (a > b) a else b

// Multi-branch if expression
val category = if (total > 10_000) {
    println("High value order")
    "VIP"
} else if (total > 1_000) {
    "PRIORITY"
} else {
    "STANDARD"
}

(2) if 表达式 vs Java if

维度 Java if Kotlin if
性质 语句 表达式
返回值 最后一行表达式的值
赋值 需要额外变量
三元运算
KOTLIN
// No ternary operator needed - if/else IS the ternary
val discount = if (total > 5_000) 0.15 else if (total > 1_000) 0.10 else 0.0

4. when 完整形态

(1) 基础 when 表达式

KOTLIN
// Exact match
val label = when (status) {
    "PENDING" -> "Waiting"
    "CONFIRMED" -> "Confirmed"
    else -> "Unknown"
}

// Multiple values in one branch
val isTerminal = when (status) {
    "SHIPPED", "DELIVERED", "CANCELLED" -> true
    else -> false
}

(2) 守卫条件(when with guard)

KOTLIN
// Conditional branches with 'in' and ranges
val pipeline = when {
    status == "CANCELLED" -> "REFUND"
    total > 10_000 && priority == "URGENT" -> "VIP_EXPRESS"
    total > 10_000 -> "VIP"
    total > 1_000 -> "PRIORITY"
    status in listOf("NEW", "PENDING") -> "QUEUE"
    else -> "STANDARD"
}

(3) 变量绑定与解构

KOTLIN
// Capture with when subject
val result = when (val response = httpClient.call()) {
    is Success -> "OK: ${response.data}"
    is Error -> "Failed: ${response.code}"
}
// response is smart-cast and available in branches

(4) 订单状态分流图

100%
flowchart TD
    A[when order.status] --> B{PENDING}
    A --> C{CONFIRMED}
    A --> D{SHIPPED}
    A --> E{CANCELLED}
    B --> B1[Waiting Queue]
    C --> C1{total > 10000?}
    C1 -->|Yes| C2[VIP Pipeline]
    C1 -->|No| C3[Standard Pipeline]
    D --> D1[Tracking Pipeline]
    E --> E1[Refund Queue]

(5) when 各形态对比

形态 语法 适用场景
精确匹配 枚举/字符串/常量
多值匹配 多值同分支
范围匹配 数值区间
类型匹配 类型分流
守卫条件 复杂条件组合
变量绑定 捕获计算结果

5. for 循环与迭代器

(1) 基础 for 循环

KOTLIN
// Range iteration
for (i in 1..10) { /* i from 1 to 10 */ }

// List iteration
for (order in orders) { println(order.id) }

// With index
for ((index, order) in orders.withIndex()) {
    println("[$index] ${order.id}")
}

// Map iteration
for ((id, status) in orderStatusMap) {
    println("$id: $status")
}

(2) 迭代器协议

KOTLIN
// Any class with operator fun iterator() can be used in for-loop
class OrderBatch(val orders: List`<Order>`) {
    operator fun iterator(): Iterator`<Order>` = orders.iterator()
}

val batch = OrderBatch(orders)
for (order in batch) { /* works! */ }

(3) for 循环方式对比

方式 语法 适用场景
区间 计数循环
集合 遍历元素
带索引 需要索引
Map 键值对遍历
自定义迭代器 自定义容器

6. while 循环

KOTLIN
// Standard while
var retryCount = 0
while (retryCount < 3) {
    val success = tryProcessOrder()
    if (success) break
    retryCount++
}

// do-while (executes at least once)
var input: String
do {
    input = readOrderStatus()
} while (input !in listOf("CONFIRM", "CANCEL"))

7. 标签与返回

(1) 循环标签

KOTLIN
// Label outer loop
loop@ for (batch in batches) {
    for (order in batch) {
        if (order.status == "CANCELLED") continue@loop  // Skip to next batch
        if (order.total > 100_000) break@loop  // Stop all processing
        process(order)
    }
}

(2) Lambda 返回

KOTLIN
// return from lambda (local return)
orders.forEach { order ->
    if (order.status == "SKIP") return@forEach  // Skip this item only
    process(order)
}

// return from enclosing function (non-local return)
// Only works in inline functions
orders.forEach { order ->
    if (order.status == "FATAL") return  // Exits main()
    process(order)
}

(3) 标签类型对比

标签类型 语法 效果
循环标签 + 跳出指定循环
continue 标签 跳到指定循环的下一次
Lambda 局部返回 只退出当前 Lambda
非局部返回 退出外层函数(仅 inline)

8. 完整示例:OrderProcessor 订单状态机

KOTLIN
// ============================================
// OrderProcessor - Status-Based Routing
// Feature: Full order status routing with when
// ============================================

enum class Status { PENDING, CONFIRMED, SHIPPED, DELIVERED, CANCELLED }
data class Order(val id: String, val total: Double, val status: Status, val region: String)

fun routeOrder(order: Order): String = when (order.status) {
    Status.PENDING -> when {
        order.region == "EU" -> "EU_COMPLIANCE_QUEUE"
        order.total > 10_000 -> "HIGH_VALUE_QUEUE"
        else -> "STANDARD_QUEUE"
    }
    Status.CONFIRMED -> when {
        order.total > 5_000 -> "EXPRESS_SHIPPING"
        else -> "REGULAR_SHIPPING"
    }
    Status.SHIPPED -> "TRACKING_UPDATE"
    Status.DELIVERED -> "COMPLETION_QUEUE"
    Status.CANCELLED -> when {
        order.total > 1_000 -> "PRIORITY_REFUND"
        else -> "STANDARD_REFUND"
    }
}

fun processBatch(orders: List`<Order>`) {
    loop@ for (order in orders) {
        when (order.status) {
            Status.CANCELLED -> {
                println("SKIP: ${order.id} cancelled")
                continue@loop
            }
            else -> {
                val pipeline = routeOrder(order)
                val priority = if (order.total > 10_000) "CRITICAL" else "NORMAL"
                println("PROCESS: ${order.id} -> $pipeline [$priority]")
            }
        }
    }
}

fun main() {
    val orders = listOf(
        Order("ORD-001", 299.99, Status.CONFIRMED, "US"),
        Order("ORD-002", 15_000.00, Status.PENDING, "EU"),
        Order("ORD-003", 2_500.00, Status.CONFIRMED, "US"),
        Order("ORD-004", 45.50, Status.CANCELLED, "US"),
        Order("ORD-005", 800.00, Status.PENDING, "ASIA"),
        Order("ORD-006", 8_000.00, Status.SHIPPED, "US")
    )

    println("=== Order Routing ===")
    processBatch(orders)

    // Summary using when expression results
    val summary = orders
        .filter { it.status != Status.CANCELLED }
        .groupBy { routeOrder(it) }
        .mapValues { (pipeline, list) -> "${list.size} orders" }

    println("\n=== Pipeline Summary ===")
    summary.forEach { (pipeline, info) -> println("  $pipeline: $info") }
}

输出:

TEXT 📖 仅展示
=== Order Routing ===
PROCESS: ORD-001 -> REGULAR_SHIPPING [NORMAL]
PROCESS: ORD-002 -> EU_COMPLIANCE_QUEUE [CRITICAL]
PROCESS: ORD-003 -> EXPRESS_SHIPPING [NORMAL]
SKIP: ORD-004 cancelled
PROCESS: ORD-005 -> STANDARD_QUEUE [NORMAL]
PROCESS: ORD-006 -> TRACKING_UPDATE [NORMAL]

=== Pipeline Summary ===
  REGULAR_SHIPPING: 1 orders
  EU_COMPLIANCE_QUEUE: 1 orders
  EXPRESS_SHIPPING: 1 orders
  STANDARD_QUEUE: 1 orders
  TRACKING_UPDATE: 1 orders

❓ 常见问题

Q Kotlin 有三元运算符 吗?
A 没有。Kotlin 用 替代三元运算符,因为 if 是表达式,功能完全等价且更可读。
Q when 不写 subject 和写 subject 有什么区别?
A 是对 x 的值/类型匹配,编译器可做穷尽检查; 是任意条件表达式,必须写 else。
Q for 循环能遍历自定义对象吗?
A 能,只要实现 返回一个 。
Q 非局部 return 有什么限制?
A 非局部 return 只能在 inline 函数的 Lambda 中使用。普通 Lambda 使用非局部 return 会导致编译错误。
Q when 分支的顺序重要吗?
A 重要。when 从上到下匹配,第一个满足条件的分支胜出。更具体的条件应放在更通用的条件之前。
Q 如何在 when 中同时匹配值和条件?
A 用守卫条件:,先匹配类型再附加条件。

📖 小节


📝 作业

  1. 基础题(难度⭐):用 表达式实现一个 函数返回三个数的最大值。提示:嵌套 if 或使用标准库
  2. 进阶题(难度⭐⭐):用 实现订单优先级判断:VIP(>10000 USD)> 高优(>1000)> 普通,已取消的跳过。提示: 守卫条件
  3. 挑战题(难度⭐⭐⭐):用循环标签实现批量订单处理:外层遍历客户批次,内层遍历订单,遇到取消订单跳过当前客户所有订单。提示: +

← 上一课 | 下一课 →

Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏