Kotlin 判空写法对比与最佳实践
在业务代码中,我们经常遇到可空对象的判空与处理。以下通过 updateRobotStatusResponse
的示例,总结三种推荐写法、优缺点对比以及团队实践建议。
写法一:let
操作符(推荐)
fun updateRobotStatusResponse(response: RobotStatusResponse?) {response?.let { resp ->if (resp.isSuccess()) {// 成功处理_robotStatusResponse.postValue(resp)Log.d(TAG, "机器人状态响应更新成功")} else {// 失败处理Log.e(TAG, "新系统机器人状态获取失败: ${resp.errorMessage}")}} ?: run {// response 为 null 的处理Log.e(TAG, "新系统机器人状态获取失败: response为null")}
}
优点:
空安全:只在非空时执行逻辑。
作用域清晰:
resp
在块内非空。Kotlin 风格统一,简洁易懂。
适用场景:逻辑不复杂,需要兼顾可读性和简洁性的情况。
写法二:先判断 null(守卫式)
fun updateRobotStatusResponse(response: RobotStatusResponse?) {
if (response == null) {
Log.e(TAG, "新系统机器人状态获取失败: response为null")
return
}if (response.isSuccess()) {
_robotStatusResponse.postValue(response)
Log.d(TAG, "机器人状态响应更新成功")
} else {
Log.e(TAG, "新系统机器人状态获取失败: ${response.errorMessage}")
}
}
优点:
直观,先处理边界条件。
提前返回,减少嵌套层次。
结构清晰,易维护。
适用场景:逻辑较复杂,判空后需要快速返回的场景。
写法三:Elvis 操作符
fun updateRobotStatusResponse(response: RobotStatusResponse?) {
if (response?.isSuccess() == true) {
_robotStatusResponse.postValue(response)
Log.d(TAG, "机器人状态响应更新成功")
} else {
val errorMsg = response?.errorMessage ?: "response为null"
Log.e(TAG, "新系统机器人状态获取失败: $errorMsg")
}
}
优点:
简洁,一行处理多种情况。
统一,失败分支集中在一起。
适用场景:简单逻辑,团队习惯“精简风格”时。
不推荐写法:when
过度使用
fun updateRobotStatusResponse(response: RobotStatusResponse?) {
when {
response == null -> Log.e(TAG, "新系统机器人状态获取失败: response为null")
response.isSuccess() -> {
_robotStatusResponse.postValue(response)
Log.d(TAG, "机器人状态响应更新成功")
}
else -> Log.e(TAG, "新系统机器人状态获取失败: ${response.errorMessage}")
}
}
问题:
结构冗余,信息增益小。
容易演变为“全局开关”,不利于维护。
推荐结论
优先:
let
写法 —— 简洁、空安全、Kotlin 风格。复杂逻辑:守卫式写法 —— 边界先行、可维护性更强。
次选:Elvis 操作符 —— 适合简单快速场景。
避免:
when
判空,除非确实存在三种以上复杂分支。