彻底讲清楚 Kotlin 的 when 表达式

一、一句话理解 when

when 是 Kotlin 中的"超级 switch":它不仅能替代 if-else 和 Java 的 switch,还能返回值、匹配任意条件、甚至当表达式用!

它是 Kotlin 最常用、最优雅的控制流工具之一


二、基础用法:替代 if-elseswitch

✅ 1. 基本匹配(类似 switch)
复制代码
val grade = "A"

when (grade) {
    "A" -> println("优秀")
    "B" -> println("良好")
    "C" -> println("及格")
    else -> println("不及格")
}

🔔 注意:不需要 break!Kotlin 自动"穿透"问题。

✅ 2. 多个值合并
复制代码
when (x) {
    1, 2, 3 -> println("小数字")
    4, 5 -> println("中等数字")
    else -> println("其他")
}
✅ 3. 区间匹配(超实用!)
复制代码
val score = 85

when (score) {
    in 90..100 -> "A"
    in 80..89 -> "B"
    in 70..79 -> "C"
    else -> "D"
}
✅ 4. 类型检查(Android 高频!)
复制代码
when (view) {
    is TextView -> view.text = "Hello"
    is ImageView -> view.setImageResource(R.drawable.icon)
    is Button -> view.isEnabled = true
    else -> Log.w("UnknownView", view::class.java.simpleName)
}

✅ 自动类型智能转换(smart cast):is TextView 后,view 直接就是 TextView 类型!


三、when 是表达式!可以返回值 💡

这是 Kotlin when 最强大的特性之一:

复制代码
val result = when (status) {
    LOADING -> "加载中..."
    SUCCESS -> "成功!"
    ERROR -> "出错了"
    else -> "未知状态"
}

// 直接用于 UI
textView.text = when (user.role) {
    "admin" -> "管理员"
    "user" -> "普通用户"
    else -> "访客"
}

每个分支必须有值(或抛异常),否则编译报错!


四、高级用法:任意条件匹配(不限于等值)

when 的每个分支可以是任意布尔表达式

复制代码
val age = 25

val category = when {
    age < 13 -> "儿童"
    age < 18 -> "青少年"
    age < 60 -> "成年人"
    else -> "老年人"
}

🔥 这相当于 if-else if-else,但更清晰!

Android 实战:权限检查
复制代码
val message = when {
    ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED ->
        "相机已授权"
    shouldShowRequestPermissionRationale(Manifest.permission.CAMERA) ->
        "请允许相机权限以使用扫码功能"
    else ->
        "需要相机权限,请在设置中开启"
}
showDialog(message)

五、配合密封类(Sealed Class)------ Android 状态管理黄金组合!

这是现代 Android 开发(尤其 Jetpack Compose)中最推荐的模式:

复制代码
sealed class UiState {
    object Loading : UiState()
    data class Success(val data: List<Item>) : UiState()
    data class Error(val msg: String) : UiState()
}

// 在 Compose 中
@Composable
fun MyScreen(viewModel: MyViewModel) {
    val uiState by viewModel.uiState.collectAsState()

    when (uiState) {
        is UiState.Loading -> CircularProgressIndicator()
        is UiState.Success -> LazyColumn {
            items(uiState.data) { item -> ItemCard(item) }
        }
        is UiState.Error -> ErrorMessage(uiState.msg)
    }
}

✅ 优势:

  • 编译器检查全覆盖:如果你加了新状态,不处理就报错!
  • 类型安全is Success 后自动解构出 data
  • 代码清晰:状态 → UI 一一对应

六、常见陷阱 & 最佳实践

❌ 陷阱1:忘记 else(当 when 用作表达式时)
复制代码
val msg = when (status) {
    LOADING -> "加载中"
    SUCCESS -> "成功"
    // ❌ 编译错误!缺少 else 或 ERROR 分支
}

✅ 解决:确保所有可能值都被覆盖,或加 else

❌ 陷阱2:在 when 中做复杂逻辑(降低可读性)
复制代码
when (user) {
    is Admin -> {
        // 20 行代码...
    }
    is Guest -> {
        // 15 行代码...
    }
}

✅ 建议:提取成函数

复制代码
when (user) {
    is Admin -> handleAdmin(user)
    is Guest -> handleGuest()
}
✅ 最佳实践1:优先用 when 替代长 if-else
复制代码
// 不好
if (type == "image") { ... }
else if (type == "video") { ... }
else if (type == "text") { ... }

// 好
when (type) {
    "image" -> ...
    "video" -> ...
    "text" -> ...
}
✅ 最佳实践2:结合 let 处理 nullable
复制代码
when (val user = fetchUser()) {
    null -> showLogin()
    else -> showProfile(user) // user 自动非空
}

七、对比 Java 的 switch

特性 Java switch Kotlin when
支持字符串 ✅(Java 7+)
支持对象 ✅(通过 equals
支持区间 ✅(in 1..10
支持类型检查 ✅(is String
支持任意表达式 ✅(when { x > 0 -> ... }
返回值 ✅(表达式!)
自动 break ❌(需手动) ✅(无穿透)

📌 Kotlin 的 when 完全碾压 Java 的 switch


八、总结一句话

when 是 Kotlin 中集"模式匹配 + 表达式返回 + 类型智能转换"于一体的控制流神器,配合密封类,能写出安全、简洁、可维护性极高的 Android 代码。

从状态管理到权限处理,从 UI 渲染到数据转换 ------ when 无处不在


💡 小练习:用 when 重构这段代码

复制代码
if (errorCode == 404) {
    message = "页面不存在"
} else if (errorCode == 500) {
    message = "服务器错误"
} else if (errorCode in 400..499) {
    message = "请求错误"
} else {
    message = "未知错误"
}

✅ 重构后:

复制代码
val message = when (errorCode) {
    404 -> "页面不存在"
    500 -> "服务器错误"
    in 400..499 -> "请求错误"
    else -> "未知错误"
}

是不是更清爽?😊

相关推荐
北城以北88884 小时前
SSM--MyBatis框架之动态SQL
java·开发语言·数据库·sql·mybatis
木易 士心4 小时前
Android 开发核心技术深度解析
android·开发语言·python
程序员烧烤5 小时前
【Java基础14】函数式接口、lamba表达式、方法引用一网打尽(下)
java·开发语言
lzq6035 小时前
Python虚拟环境全指南:venv与conda对比与实践
开发语言·python·conda
QING6185 小时前
Jetpack Compose 条件布局与 Layout 内在测量详解
android·kotlin·android jetpack
一念杂记5 小时前
没网太崩溃!手机电脑网络共享,简单几步搞定网络共享,再也不用为没网担忧~
android·windows
小年糕是糕手5 小时前
【数据结构】常见的排序算法 -- 插入排序
c语言·开发语言·数据结构·学习·算法·leetcode·排序算法
星释5 小时前
Rust 练习册 4:Deref trait 与智能指针
开发语言·后端·rust
心随雨下5 小时前
Java中将System.out内容写入Tomcat日志
java·开发语言·tomcat