彻底讲清楚 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 -> "未知错误"
}

是不是更清爽?😊

相关推荐
Kapaseker19 小时前
Compose 进阶—巧用 GraphicsLayer
android·kotlin
黄林晴20 小时前
Android17 为什么重写 MessageQueue
android
阿巴斯甜2 天前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker2 天前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq95272 天前
Andorid Google 登录接入文档
android
黄林晴2 天前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab2 天前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读
城东米粉儿2 天前
Android MediaPlayer 笔记
android
Jony_2 天前
Android 启动优化方案
android
阿巴斯甜2 天前
Android studio 报错:Cause: error=86, Bad CPU type in executable
android