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

相关推荐
广药门徒9 分钟前
OpenMV IDE 的图像接收缓冲区原理
前端·人工智能·python
霸王蟹13 分钟前
常见面试题:Webpack的构建流程简单说一下。
前端·笔记·学习·webpack·node.js·vue
黄暄17 分钟前
Linux项目部署全攻略:从环境搭建到前后端部署实战
java·linux·运维·服务器·前端·后端·持续部署
island131442 分钟前
JAVA Web 期末速成
java·开发语言·前端
小峰编程1 小时前
Python函数——万字详解
linux·运维·服务器·开发语言·前端·网络·python
11054654013 小时前
23、电网数据管理与智能分析 - 负载预测模拟 - /能源管理组件/grid-data-smart-analysis
前端·能源
开发者小天3 小时前
React中startTransition的使用
前端·react.js·c#
@PHARAOH4 小时前
WHAT - 缓存命中 Cache Hit 和缓存未命中 Cache Miss
前端·缓存
海天胜景4 小时前
无法加载文件 E:\Program Files\nodejs\npm.ps1,因为在此系统上禁止运行脚本
前端·npm·node.js
MingT 明天你好!4 小时前
在vs code 中无法运行npm并报无法将“npm”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查
前端·npm·node.js·visual studio code