别再手写 if/else 判断了!赶紧来掌握 Kotlin 的 coerce 三兄弟吧

在日常开发中,我们常常需要对数值进行范围限制,比如限制用户输入的年龄在 0~120 之间,又或者限制图片透明度在 0f ~1f 之间。这类场景中,我们第一反应会写出类似这样的代码:

kotlin 复制代码
val age = if (inputAge < 0) 0 else if (inputAge > 120) 120 else inputAge

虽然功能上没毛病,但写多了会不会觉得还是有些繁琐?其实 Kotlin 已经为我们提供了优雅的解决方案:coerceIn、coerceAtLeast 和 coerceAtMost,合称为 coerce 三兄弟 。上述代码用coerceIn来写就会变成:inputAge.coerceIn(0,120),怎么样,是不是更简洁一些。

coerce 三兄弟简介

这个coerce单词还挺别捏,特意查了下词典:

来跟我读:kou-e-si,分成三节来看还简单点:co-er-ce!

1、coerceIn(min, max) 限制数值在给定范围之内,超出则返回边界值。使用示例如:val clamped = value.coerceIn(min, max)

2、coerceAtLeast(min) 确保值不小于指定最小值,小于则返回最小值。如:val atLeast = value.coerceAtLeast(min)

3、coerceAtMost(max) 确保值不大于指定最大值,大于则返回最大值。如:val atMost = value.coerceAtMost(max)

使用示例对比

1、假设正在开发一个视频播放器,需要控制播放速度(范围为 0.5x 到 2.0x):

使用coerceIn 对应的 if/else 实现
val speed = inputSpeed.coerceIn(0.5f, 2.0f) val speed = if (inputSpeed < 0.5f) 0.5f else if (inputSpeed > 2.0f) 2.0f else inputSpeed

2、再比如限制用户昵称长度最少为 2 个字符:

使用coerceAtLeast 对应的 if/else 实现
val minLength = nickname.length.coerceAtLeast(2) val minLength = if (nickname.length < 2) 2 else nickname.length

3、限制上传图片不能超过 5MB:

使用coerceAtMost 对应的 if/else 实现
val fileSize = image.sizeInMb.coerceAtMost(5) val fileSize = if (image.sizeInMb > 5) 5 else image.sizeInMb

进阶用法:自定义类型也能用

coerceXXX 方法不仅适用于 Int、Float、Double这些基本类型,还可以用于实现了 Comparable 接口的自定义类,源码如下:

kotlin 复制代码
//T.coerceAtLeast
public fun <T : Comparable<T>> T.coerceAtLeast(minimumValue: T): T {
    return if (this < minimumValue) minimumValue else this
}

//T.coerceAtMost
public fun <T : Comparable<T>> T.coerceAtMost(maximumValue: T): T {
    return if (this > maximumValue) maximumValue else this
}

//T.coerceIn
public fun <T : Comparable<T>> T.coerceIn(minimumValue: T?, maximumValue: T?): T {
    if (minimumValue !== null && maximumValue !== null) {
        if (minimumValue > maximumValue) throw IllegalArgumentException("Cannot coerce value to an empty range: maximum $maximumValue is less than minimum $minimumValue.")
        if (this < minimumValue) return minimumValue
        if (this > maximumValue) return maximumValue
    }
    else {
        if (minimumValue !== null && this < minimumValue) return minimumValue
        if (maximumValue !== null && this > maximumValue) return maximumValue
    }
    return this
}

示例:

kotlin 复制代码
data class Version(val code: Int) : Comparable<Version> {
    override fun compareTo(other: Version): Int = this.code - other.code
}

val v1 = Version(1)
val v2 = Version(5)
val v3 = Version(10)

val current = Version(7)
val clamped1 = current.coerceIn(v1, v3)
val clamped2 = current.coerceIn(v1, v2)
val clamped3 = current.coerceIn(v2, v3)

Log.d("test", "$clamped1,$clamped2,$clamped3") 
//输出:Version(code=7),Version(code=5),Version(code=7)

总结

语法 含义 示例 等价逻辑
x.coerceAtLeast(min) 限制最小值 (-5).coerceAtLeast(0) → 0 if (x < min) min else x
x.coerceAtMost(max) 限制最大值 150.coerceAtMost(100) → 100 if (x > max) max else x
x.coerceIn(min, max) 限制值在区间内 150.coerceIn(0, 100) → 100, -20.coerceIn(0, 100) → 0 min(max(x, min), max)

使用 coerceIn、coerceAtLeast 和 coerceAtMost,可以大大简化常见的范围判断逻辑,提升代码的可读性与优雅度。告别繁琐的 if/else,让 Kotlin 的扩展函数替你完成繁重的边界控制!

别再手写判断了,是时候把 coerce 三兄弟收入囊中了!

相关推荐
alexhilton3 分钟前
用Konsist与Lint强制执行设计系统契约
android·kotlin·android jetpack
北京自在科技4 小时前
谷歌安卓 Gemini 迎来界面改版,Find Hub 接入 Gemini 支持物品记忆查找
android·安卓
YB13756 小时前
Jetpack Compose 动画Modifier.animateItem()
android
2401_885885047 小时前
巴林语音通知接口如何对接?系统告警语音API接入教程
android·前端·网络·python·语音识别
收纳过往7 小时前
数据库加索引的时机:慢查询日志说话
android·开发语言·数据库·python·低代码·rxjava
狂热开发者8 小时前
车载中控要给鸿蒙用户,能不能和 Android 共用一个二维码?
android·华为·harmonyos
.Bryce.9 小时前
T2-LLM评测不等于Agent评测
android·java·人工智能·后端·gpt·agent·1024程序员节
美狐美颜SDK开放平台10 小时前
视频美颜SDK如何应对快速转头与大幅度面部动作?
android·人工智能·ios·音视频·直播美颜sdk·视频美颜sdk
2601_9689007710 小时前
玻璃深加工的工艺窗口:4 道工序的温度与时间参数边界
android·java·javascript
好的佩奇0110 小时前
Dart 之类修饰符
android·flutter·dart