Kotlin 之 when 表达式

Kotlin 的 when 表达式是一种强大的条件控制结构,可以替代传统的 switch-case 语句,并支持更灵活的条件匹配逻辑。以下是其核心特性及用法:


一、基础语法与对比

1. ‌与 Java switch 的对比
特性 ‌**Kotlin when**‌ ‌**Java switch**‌
支持类型 任意类型(包括非枚举、非整型) 仅支持整型、枚举、字符串(Java 7+)
分支条件 可为表达式(如范围、类型、复杂逻辑) 仅常量值
默认分支 可选的 else(作为表达式时需覆盖所有情况) 必须显式处理未覆盖情况或使用 default
返回值 可作为表达式返回值 仅流程控制,无返回值
2. ‌基本语法
rust 复制代码
rust
 代码解读
复制代码
// 作为表达式(必须有 else)
val result = when (input) {
    1 -> "One"
    2 -> "Two"
    else -> "Unknown"
}

// 作为语句(else 可选)
when (x) {
    0 -> println("Zero")
    1 -> println("One")
    else -> println("Other")
}

二、高级匹配模式

1. ‌多条件匹配

使用逗号 ,in 合并多个条件:

rust 复制代码
rust
 代码解读
复制代码
when (value) {
    0, 1 -> "Binary digit"     // 匹配 0 或 1
    in 2..10 -> "Single digit" // 匹配 2~10
    is String -> "String type"  // 类型匹配
    else -> "Unknown"
}
2. ‌类型检查与智能转换

结合 is 进行类型判断后,自动完成类型转换:

kotlin 复制代码
kotlin
 代码解读
复制代码
fun process(obj: Any) = when (obj) {
    is Int -> "Int: ${obj * 2}"       // obj 自动转为 Int
    is String -> "String: ${obj.length}" // obj 自动转为 String
    else -> "Unknown type"
}
3. ‌无参数模式

when 不传参数时,每个分支条件需为布尔表达式:

rust 复制代码
rust
 代码解读
复制代码
when {
    score >= 90 -> "A"
    score >= 80 -> "B"
    score >= 60 -> "C"
    else -> "D"
}
4. ‌结合范围(Range)

使用 in!in 检查值是否在区间内:

rust 复制代码
rust
 代码解读
复制代码
val temperature = 25
val status = when (temperature) {
    in -10..0 -> "Freezing"
    in 1..15 -> "Cold"
    in 16..25 -> "Warm"
    else -> "Hot"
}

三、与密封类(Sealed Class)结合

when 可强制覆盖密封类的所有子类,避免遗漏分支(无需 else):

kotlin 复制代码
kotlin
 代码解读
复制代码
sealed class Result {
    data class Success(val data: String) : Result()
    data class Error(val message: String) : Result()
}

fun handleResult(result: Result) = when (result) {
    is Result.Success -> "Data: ${result.data}"
    is Result.Error -> "Error: ${result.message}"
    // 无需 else,因密封类已覆盖所有可能
}

四、性能优化与注意事项

  1. 分支顺序

    将高频匹配条件放在前面,减少不必要的检查。例如:

    scss 复制代码
    scss
     代码解读
    复制代码
    when (statusCode) {
        200 -> handleSuccess()
        404 -> handleNotFound()
        else -> handleError() // 低频错误统一处理
    }
  2. 编译优化

    Kotlin 编译器将 when 转换为高效的跳转表(类似 switchtableswitch),尤其在匹配整数常量时性能接近原生 switch

  3. 避免复杂条件

    若分支逻辑过于复杂,优先将其封装为独立函数或使用策略模式替代。


五、实际应用场景

1. ‌**替代多层 if-else**‌

简化复杂的条件链:

ini 复制代码
ini
 代码解读
复制代码
// 传统 if-else
if (user.role == "Admin") { ... }
else if (user.role == "Editor" && user.isActive) { ... }
else { ... }

// 使用 when 更清晰
when {
    user.role == "Admin" -> ...
    user.role == "Editor" && user.isActive -> ...
    else -> ...
}
2. ‌处理枚举类型

清晰匹配枚举值:

kotlin 复制代码
kotlin
 代码解读
复制代码
enum class Direction { NORTH, SOUTH, EAST, WEST }

fun move(direction: Direction) = when (direction) {
    Direction.NORTH -> "Move up"
    Direction.SOUTH -> "Move down"
    Direction.EAST, Direction.WEST -> "Move horizontally"
}
3. ‌Android 开发中的典型用法

处理点击事件或状态:

kotlin 复制代码
kotlin
 代码解读
复制代码
override fun onClick(view: View) {
    when (view.id) {
        R.id.btn_submit -> submitForm()
        R.id.btn_cancel -> closeActivity()
        R.id.btn_retry -> loadData()
    }
}

六、常见错误与解决

  1. 缺少 else 分支(作为表达式时)

    kotlin 复制代码
    kotlin
     代码解读
    复制代码
    val value = when (input) {  // 编译错误:缺少 else
        1 -> "One"
    }
  2. 类型匹配后未自动转换

    确保使用 is 后直接访问类型属性:

    scss 复制代码
    scss
     代码解读
    复制代码
    kotlinCopy Code
    when (obj) {
        is String -> println(obj.length) // 正确:obj 自动转为 String
        is Int -> println(obj + 1)       // 正确:obj 自动转为 Int
    }

补充

Kotlin的 if 是表达式 有返回值的

总结

Kotlin 的 when 表达式通过以下特性显著提升代码质量:

  • 灵活性‌:支持任意条件表达式、类型检查及范围匹配。

  • 安全性‌:强制覆盖密封类所有子类,减少逻辑遗漏。

  • 简洁性 ‌:替代多层 if-else,提升代码可读性。

相关推荐
zhougl9961 小时前
html处理Base文件流
linux·前端·html
花花鱼1 小时前
node-modules-inspector 可视化node_modules
前端·javascript·vue.js
HBR666_1 小时前
marked库(高效将 Markdown 转换为 HTML 的利器)
前端·markdown
careybobo3 小时前
海康摄像头通过Web插件进行预览播放和控制
前端
杉之4 小时前
常见前端GET请求以及对应的Spring后端接收接口写法
java·前端·后端·spring·vue
喝拿铁写前端4 小时前
字段聚类,到底有什么用?——从系统混乱到结构认知的第一步
前端
再学一点就睡4 小时前
大文件上传之切片上传以及开发全流程之前端篇
前端·javascript
木木黄木木5 小时前
html5炫酷图片悬停效果实现详解
前端·html·html5
请来次降维打击!!!6 小时前
优选算法系列(5.位运算)
java·前端·c++·算法
難釋懷6 小时前
JavaScript基础-移动端常见特效
开发语言·前端·javascript