把數值關進籠子:用Kotlin的coerce三兄弟玩轉邊界控制
寫代碼就像玩策略游戲,總得給數值設定「安全區」。比如游戲角色的血量不能跌破0、奶茶甜度不能超過200%、文件體積不能突破存儲上限...今天教你用Kotlin自帶的三個「數值牢籠」優雅解決邊界問題!
先看一段讓你血壓升高的代碼
// 傳統方式:用if/else給數值上枷鎖
fun processUserAge(age: Int): Int {
var result = age
if (age < 0) { // 第一道防線
result = 0
} else if (age > 120) { // 第二道防線
result = 120
}
return result
}
// 使用示例
println(processUserAge(-5)) // 輸出:0
println(processUserAge(130)) // 輸出:120
println(processUserAge(25)) // 輸出:25
這段代碼就像給數值套了三層防盜門:
? 檢查是否小于最小值 → 關進地下室
? 檢查是否大于最大值 → 鎖上天臺
? 中間值才能安全通行
痛點暴擊:
? 邊界條件需要重復判斷
? 修改范圍時要同時調整兩處數字
? 處理浮點數時容易遺漏精度問題
Kotlin提供了三個非常實用的方法——coerceIn、coerceAtLeast 和 coerceAtMost,可以幫助我們更簡潔地實現這些功能。接下來,讓我們一起來看看這三位coerce兄弟的具體用法吧!
coerceIn:給數值上雙保險鎖
coerceIn(min, max)方法的作用是將一個數值限制在一個指定的范圍內。如果數值超出了這個范圍,則返回相應的邊界值。
場景:游戲角色的血量必須維持在0-100之間
var hp = 120
hp = hp.coerceIn(0, 100) // 超過上限直接鎖死
println("當前血量:$hp") // 輸出:當前血量:100
hp = -15
hp = hp.coerceIn(0, 100) // 跌破下限自動修正
println("瀕死保護:$hp") // 輸出:瀕死保護:0
隱藏技巧:范圍值可以動態計算,比如根據角色等級調整血量上限
val maxHp = level * 50
currentHp = currentHp.coerceIn(0, maxHp)
coerceAtLeast:設置數值底褲
coerceAtLeast(min)方法用于確保一個數值不小于某個最小值。如果數值小于最小值,則返回最小值;否則返回原數值。
場景:奶茶店小程序限制最低甜度為30%
fun setSweetness(percent: Int): Int {
return percent.coerceAtLeast(30) // 低于30自動補到最低值
}
println(setSweetness(25)) // 輸出:30
println(setSweetness(50)) // 輸出:50
實戰應用:防止負數導致的bug,比如物品數量永遠不會小于零:
var itemCount = -5
itemCount = itemCount.coerceAtLeast(0) // 強制歸零
coerceAtMost:給數值蓋天花板
coerceAtMost(max)方法則是用來確保一個數值不大于某個最大值。如果數值超過了最大值,則返回最大值;否則返回原數值。
場景:上傳圖片限制5MB以內
fun checkImageSize(mb: Float): Float {
return mb.coerceAtMost(5f) // 超過5MB的自動壓縮標記
}
println(checkImageSize(6.8f)) // 輸出:5.0
println(checkImageSize(3.2f)) // 輸出:3.2
組合技:動態計算文件體積上限,根據用戶會員等級調整:
val maxSize = if (isVip) 10f else 5f
fileSize = fileSize.coerceAtMost(maxSize)
進階玩法:給自定義類型裝護欄
除了基本的數值類型,coerce系列方法還可以用于實現了Comparable接口的自定義類。
場景:游戲版本號控制系統(v1.0-v3.0)
// 自定義版本類
data class GameVersion(val major: Int, val minor: Int) : Comparable<GameVersion> {
overridefun compareTo(other: GameVersion): Int {
return when {
major != other.major -> major - other.major
else -> minor - other.minor
}
}
}
// 版本控制
val minVer = GameVersion(1, 0)
val maxVer = GameVersion(3, 0)
val current = GameVersion(4, 2)
val safeVer = current.coerceIn(minVer, maxVer)
println(safeVer) // 輸出:GameVersion(major=3, minor=0)
避坑指南
1. 范圍顛倒陷阱:coerceIn(100, 0)會導致崩潰,就像把護欄裝反了
val safeValue = 50.coerceIn(100, 0) // 拋出IllegalArgumentException
2. 浮點數精度問題:處理金額時推薦使用BigDecimal
val money = BigDecimal("15.5")
money.coerceIn(BigDecimal("10"), BigDecimal("20"))
3. 空值防御:處理可空類型時要先判空
val maybeNumber: Int? = null
maybeNumber?.coerceAtLeast(0) ?: 0
結論
coerce方法就像代碼界的智能護欄,既省時又美觀!
? 上限下限都要管 → coerceIn
? 防止數值穿地心 → coerceAtLeast
? 避免突破大氣層 → coerceAtMost
? 自定義類型要繼承Comparable接口
用好這三兄弟,讓你的代碼像裝了智能圍欄,既安全又優雅!