Kotlin: Kotlin控制流详解
最后更新:2026-08-26
Kotlin 的控制流不仅是流程控制—— 和 是表达式,有返回值,让 Charlie 的订单分流逻辑既安全又简洁。
1. 你将学到
- 是表达式:
- 完整形态:多分支、守卫条件、变量绑定
-
- 迭代器:遍历集合、区间、Map
- 标签与返回: / /
- Charlie 实战: 订单分流
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) 订单状态分流图
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 用守卫条件:,先匹配类型再附加条件。
📖 小节
- 是表达式,可直接赋值给变量,替代 Java 三元运算符
- 是 switch 的升级版:多值匹配、范围、类型、守卫条件
- 作为表达式时编译器强制穷尽检查,防止遗漏分支
- 支持区间、集合、Map、自定义迭代器
- 标签 + 精确控制嵌套循环跳转
- Lambda 局部返回 vs 非局部返回
📝 作业
- 基础题(难度⭐):用 表达式实现一个 函数返回三个数的最大值。提示:嵌套 if 或使用标准库
- 进阶题(难度⭐⭐):用 实现订单优先级判断:VIP(>10000 USD)> 高优(>1000)> 普通,已取消的跳过。提示: 守卫条件
- 挑战题(难度⭐⭐⭐):用循环标签实现批量订单处理:外层遍历客户批次,内层遍历订单,遇到取消订单跳过当前客户所有订单。提示: +