一、一句话理解 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 -> "未知错误"
}
是不是更清爽?😊