ZetCode

Kotlin when 关键字

最后修改于 2025 年 4 月 19 日

Kotlin 的 when 关键字是一个强大的条件表达式,它取代了 Java 的 switch 语句。它比传统的 switch 语句提供了更多的灵活性和功能。本教程通过实际例子深入探讨了 when 关键字。

基本定义

Kotlin 中的 when 关键字既可以作为语句,也可以作为表达式。它可以简洁地检查多个条件,并支持各种匹配模式。与 Java 的 switch 不同,它适用于任何数据类型。

基本的 when 表达式

when 最简单的形式是将一个值与几个常量进行匹配。它类似于 switch 语句,但更强大。每个分支按顺序检查,直到找到匹配项。

BasicWhen.kt
package com.zetcode

fun main() {

    val x = 2
    
    when (x) {
        1 -> println("x is 1")
        2 -> println("x is 2")
        3 -> println("x is 3")
        else -> println("x is neither 1, 2, nor 3")
    }
}

此示例显示了一个基本的 when 表达式,用于匹配整数值。输出将是 "x is 2",因为这是匹配的情况。else 分支处理所有其他可能性。

when 作为表达式

when 可以用作返回值的表达式。在这种形式中,除非编译器可以证明涵盖了所有情况,否则需要 else 分支。每个分支返回一个值。

WhenExpression.kt
package com.zetcode

fun main() {

    val x = 3
    
    val result = when (x) {
        1 -> "One"
        2 -> "Two"
        3 -> "Three"
        else -> "Unknown"
    }
    
    println(result) // Output: Three
}

在这里,when 用作返回字符串的表达式。该值被分配给 result,然后被打印出来。这比使用 if-else 链来实现相同的目的更简洁。

一个分支中的多个条件

when 允许使用逗号在一个分支中组合多个条件。当多个值应该执行相同的代码块时,这使得代码更简洁。它比重复相同的代码更清晰。

MultipleConditions.kt
package com.zetcode

fun main() {

    val x = 5
    
    when (x) {
        1, 3, 5 -> println("x is odd and between 1-5")
        2, 4, 6 -> println("x is even and between 2-6")
        else -> println("x is outside 1-6 range")
    }
}

此示例将奇数和偶数分组到不同的分支中。输出将指示 5 是一个介于 1-5 之间的奇数。这种方法减少了代码重复。

when 中的范围检查

when 可以使用 in 运算符检查一个值是否在范围内。这比只适用于常量值的传统 switch 语句更强大。范围使代码更具表达力。

RangeChecks.kt
package com.zetcode

fun main() {

    val score = 85
    
    val grade = when (score) {
        in 90..100 -> "A"
        in 80..89 -> "B"
        in 70..79 -> "C"
        in 60..69 -> "D"
        else -> "F"
    }
    
    println("Grade: $grade") // Output: Grade: B
}

此示例根据分数范围分配字母等级。in 运算符检查分数是否落在每个范围内。输出显示了对于 85 分的 B 等级。

when 的类型检查

when 可以使用 is 运算符检查对象的类型。这与智能类型转换结合使用,以访问特定于类型的属性。这是 Java 中 instanceof 检查的强大替代方案。

TypeChecks.kt
package com.zetcode

fun describe(obj: Any): String = when (obj) {
    is String -> "String with length ${obj.length}"
    is Int -> "Integer with value $obj"
    is Double -> "Double with value $obj"
    else -> "Unknown type"
}

fun main() {

    println(describe("Hello")) // String with length 5
    println(describe(42))      // Integer with value 42
    println(describe(3.14))    // Double with value 3.14
    println(describe(true))    // Unknown type
}

describe 函数使用 when 来检查其参数的类型。智能类型转换允许访问特定于类型的属性,例如 String 的长度。每个类型都获得不同的描述字符串。

when 没有参数

when 可以不带参数使用,就像一系列 if-else 条件。每个分支条件必须计算为布尔值。这种形式对于不符合标准模式的复杂条件很有用。

WhenWithoutArgument.kt
package com.zetcode

fun main() {

    val x = 15
    val y = 10
    
    when {
        x > y -> println("x is greater than y")
        x < y -> println("x is less than y")
        else -> println("x and y are equal")
    }
}

此示例在不使用 when 的参数的情况下比较两个变量。每个分支都包含一个布尔表达式。输出显示在这种情况下 x 大于 y。

when 与密封类

when 与密封类配合使用效果特别好,确保处理了所有子类。当涵盖所有可能的子类型时,编译器可以验证详尽性。这对于状态管理很有用。

SealedClassWhen.kt
package com.zetcode

sealed class Result
class Success(val data: String) : Result()
class Error(val message: String) : Result()

fun handleResult(result: Result) = when (result) {
    is Success -> println("Success: ${result.data}")
    is Error -> println("Error: ${result.message}")
}

fun main() {

    handleResult(Success("Data loaded"))
    handleResult(Error("Connection failed"))
}

此示例演示了 when 如何处理密封类层次结构。编译器知道所有可能的 Result 子类型,因此不需要 else 分支。每个子类都以不同的方式处理。

when 的最佳实践

来源

Kotlin when 文档

本教程深入介绍了 Kotlin 的 when 关键字,展示了它作为语句和表达式的多功能性。我们探讨了各种匹配模式,包括常量、范围、类型和密封类。正确使用 when 可以使条件逻辑更简洁、更具可读性。

作者

我叫 Jan Bodnar,是一位热情的程序员,拥有多年的编程经验。自 2007 年以来,我一直在撰写编程文章。到目前为止,我已经撰写了 1400 多篇文章和 8 本电子书。我拥有超过八年的编程教学经验。

列出 所有 Kotlin 教程