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,提升代码可读性。

相关推荐
凌晨一点的程序员4 分钟前
antd中的表格穿梭框(Transfer)如何使用
前端·javascript·html·react·antd·transfer
^小桃冰茶1 小时前
HTML 从标签到动态效果的基础
前端·html
火柴盒zhang1 小时前
基于HTML CANVAS和EXCEL的xlsx文件展示工具websheet
前端·javascript·html·spreadsheet·websheet
一城烟雨_6 小时前
vue3 实现将html内容导出为图片、pdf和word
前端·javascript·vue.js·pdf
树懒的梦想6 小时前
调整vscode的插件安装位置
前端·cursor
低代码布道师7 小时前
第二部分:网页的妆容 —— CSS(下)
前端·css
一纸忘忧7 小时前
成立一周年!开源的本土化中文文档知识库
前端·javascript·github
涵信8 小时前
第九节:性能优化高频题-首屏加载优化策略
前端·vue.js·性能优化
前端小巷子8 小时前
CSS单位完全指南
前端·css
SunTecTec9 小时前
Flink Docker Application Mode 命令解析 - 修改命令以启用 Web UI
大数据·前端·docker·flink