404 Not Found

404 Not Found


nginx

Kotlin Control Flow Explained

Kotlin's control flow isn't just flow control — if and when are expressions with return values, making Charlie's order routing logic both safe and concise.

1. What You'll Learn


2. An Architect's Real Story

(1) Pain Point: Nested if-else Hell

Charlie's Java OrderProcessor used 5 levels of nested if-else to route orders by status — 120 lines just to decide which pipeline to use. When new team member Bob joined, he got the branch conditions wrong 3 times, causing production incidents.

(2) Kotlin's when Expression Solution

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
}

when expression exhaustiveness checking + compiler guard: a missing branch is a compile error. Bob can never introduce such bugs again.


3. if Expression

(1) if is an Expression with a Return Value

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 Expression vs Java if

Dimension Java if Kotlin if
Nature Statement Expression
Return value None Value of last expression
Assignment Needs extra variable val x = if(...)...
Ternary operator ?: if/else
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 in All Its Forms

(1) Basic when Expression

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) Guard Conditions (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) Variable Binding and Destructuring

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) Order Status Routing Diagram

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 Forms Comparison

Form Syntax Use Case
Exact match when(status) Enums / strings / constants
Multi-value match "A", "B" -> ... Multiple values, same branch
Range match in 1..10 Numeric intervals
Type match is String Type-based routing
Guard conditions when { ... } Complex condition combos
Variable binding when(val x = ...) Capture computed values

5. for Loop and Iterators

(1) Basic for Loop

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) Iterator Protocol

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 Loop Patterns Comparison

Pattern Syntax Use Case
Range for (i in 1..10) Counting loops
Collection for (o in orders) Iterating elements
With index for ((i, o) in ...) Need index
Map for ((k,v) in map) Key-value iteration
Custom iterator operator fun iterator() Custom containers

6. while Loop

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. Labels and Returns

(1) Loop Labels

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 Returns

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) Label Types Comparison

Label Type Syntax Effect
Loop label loop@ + break@loop Exit specified loop
continue label continue@loop Jump to next iteration of specified loop
Lambda local return return@forEach Exit only current lambda
Non-local return return Exit enclosing function (inline only)

8. Complete Example: OrderProcessor Order State Machine

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") }
}

Output:

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

❓ FAQ

Q Does Kotlin have a ternary operator ?:?
A No. Kotlin uses if/else instead of a ternary operator because if is an expression — functionally equivalent and more readable.
Q What's the difference between when with and without a subject?
A when(x) matches against x's value/type with compiler exhaustiveness checking; when { } is arbitrary conditional expressions and must include else.
Q Can a for loop iterate over custom objects?
A Yes, as long as the class implements operator fun iterator() returning an Iterator.
Q What are the limitations of non-local return?
A Non-local return can only be used in lambdas of inline functions. Using non-local return in a regular lambda causes a compile error.
Q Does branch order matter in when?
A Yes. when matches top-to-bottom, and the first satisfied branch wins. Put more specific conditions before more general ones.
Q How do I match both a value and a condition in when?
A Use guard conditions: is Order && total > 1000 -> — first match the type, then add the condition.

📖 Summary


📝 Exercises

  1. Beginner (⭐): Use if expressions to implement a maxOfThree function returning the maximum of three numbers. Hint: nested if or use maxOf() from the standard library
  2. Intermediate (⭐⭐): Use when to implement order priority determination: VIP (>10000 USD) > High Priority (>1000) > Normal, skip cancelled orders. Hint: when guard conditions
  3. Challenge (⭐⭐⭐): Use loop labels to implement batch order processing: outer loop over customer batches, inner loop over orders — skip the entire customer batch if a cancelled order is found. Hint: loop@ + continue@loop

← Previous | Next →

Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

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

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