彻底讲清楚 Kotlin 的 when 表达式

一、一句话理解 when

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

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


二、基础用法:替代 if-else 和 switch

✅ 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 -> "未知错误"
}

是不是更清爽?😊

相关推荐
gz927cool5 分钟前
Python 全栈应用最佳实践完整指南
开发语言·python·ai
CoderYanger23 分钟前
Java EE 进阶:5. Spring IoC&DI(第三弹):Spring DI
java·开发语言·spring boot·spring·面试·java-ee·mvc
思想觉悟26 分钟前
SEAndroid实战
android·linux·c++
AIFQuant28 分钟前
Python期货行情API接入:股指、黄金、原油多品种数据管道实战
开发语言·python·金融·区块链·量化开发
echome88829 分钟前
JavaScript async/await 错误处理:别让 Promise 静默失败
开发语言·前端·javascript·promise
运维行者_32 分钟前
供应链安全成最大风险源,企业如何构建可控的运维体系?
运维·开发语言·网络·数据库·安全·云计算·流量监控
.YM.Z41 分钟前
优选算法——【双指针算法2】C++实现
开发语言·c++·算法
逆向编程1 小时前
MATLAB高级数据结构:cell、struct与table深度应用
开发语言·数据结构·matlab
思想觉悟1 小时前
Aosp开发磨刀石之ADB速查
android·c++
努力努力再努力wz1 小时前
【Lua入门系列】从 Table 到元表与元方法:一文理解 Lua 的行为扩展机制
开发语言·junit·lua