彻底讲清楚 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 = 85when (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 = trueelse -> 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 = 25val 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 -> "未知错误"
}
是不是更清爽?😊
