1. 概述
在软件开发中,输入校验和数据状态检查是构建可靠系统的关键环节。本文将介绍如何使用 Kotlin 标准库中内置的 Preconditions 工具函数进行参数校验与状态断言。
这些函数能显著减少样板代码,让逻辑更清晰。对于有经验的开发者来说,掌握它们不仅能提升代码健壮性,还能避免不少线上踩坑。
2. 前置条件检查函数
Kotlin 在标准库中提供了一组简洁高效的前置条件检查工具函数,位于 kotlin
包下,无需引入额外依赖即可使用。它们通过抛出异常的方式中断非法流程,常用于方法入口处的防御性编程。
2.1 require():用于参数合法性校验
require()
函数用于验证传入参数是否满足业务前提。它接收两个参数:
value: Boolean
:待验证的布尔表达式lazyMessage: () -> Any
:延迟计算的错误消息(lambda 形式)
✅ 行为规则:当 value
为 false
时,抛出 IllegalArgumentException
,携带 lazyMessage
提供的信息。
⚠️ 使用 lambda 而非直接字符串的好处是:只有在校验失败时才会执行字符串拼接或复杂逻辑,避免不必要的性能开销。
fun printPositiveNumber(num: Int) {
require(num > 0) { "Number must be positive" }
println(num)
}
踩坑提醒:不要用
require(condition, "message")
这种写法 —— 第二个参数必须是 lambda!
2.2 check():用于对象内部状态校验
check()
的签名与 require()
完全一致,但语义不同:
❌ require()
针对外部输入(arguments)
✅ check()
针对内部状态(state),比如对象字段、缓存、配置等
其行为是:若条件不成立,则抛出 IllegalStateException
。
来看一个典型场景 —— 计算平均值前确保列表非空:
class AverageCalculator() {
private val numbers: MutableList<Int> = mutableListOf()
fun add(number: Int) {
numbers.add(number)
}
fun clear() {
numbers.clear()
}
fun average(): Double {
check(numbers.size > 0) { "Must have numbers to be able to perform an average." }
println("Computing averages of numbers: $numbers")
return numbers.average()
}
}
📌 注意:这里不是用户传参,而是类自身维护的状态,因此用 check()
更符合语义规范。
2.3 requireNotNull():校验可空参数非空
当我们接收可能为 null 的参数时,可以用 requireNotNull()
快速断言其非空,并安全解包。
✅ 若值为 null
,抛出 IllegalArgumentException
✅ 否则返回原值(自动类型推导为非空类型)
class Person(name: String?, age: Int?) {
val name: String = requireNotNull(name) { "Name must not be null" }
val age: Int = requireNotNull(age) { "Age must not be null" }
}
这比手写 if (name == null) throw IllegalArgumentException(...)
简洁得多,且具备类型提升能力。
2.4 checkNotNull():校验内部状态中的非空引用
与 requireNotNull()
对应,checkNotNull()
用于检查对象内部状态中不应为 null 的字段或临时变量。
✅ 条件:值为 null
时抛出 IllegalStateException
✅ 场景:适用于运行时状态一致性检查
fun processStrings(list: List<String?>): String {
val nonNullStrings = mutableListOf<String>()
for (string in list) {
checkNotNull(string) { "The list must not contain null elements" }
nonNullStrings.add(string)
}
return "Processed strings: $nonNullStrings"
}
📌 小技巧:结合 mapNotNull { checkNotNull(it) }
可实现链式处理。
2.5 error():主动抛出运行时异常
error()
是一个极简的辅助函数,定义如下:
fun error(message: Any): Nothing
其中 Nothing
是 Kotlin 特有的“无返回”类型,表示该函数永远不会正常返回。
✅ 用途:明确表示此处应发生异常,终止流程
✅ 适合场景:未支持的分支、不可达路径、资源缺失等
示例一:除零保护
fun divide(a: Int, b: Int): Int {
if (b == 0) {
error("Cannot divide by zero")
}
return a / b
}
示例二:JSON 类型匹配兜底
fun processJsonArrayOrObject(json: String): JsonNode {
val genericJson: JsonNode = jacksonObjectMapper().readTree(json)
when (genericJson) {
is ArrayNode -> { /* we have a json list */ }
is ObjectNode -> { /* we have an object */ }
else -> error("This function only handles list and object wrappers in Json")
}
return genericJson
}
⚠️ 注意:
error()
抛的是IllegalStateException
,不适合替代参数校验。如果是用户输入问题,请优先使用require()
。
3. 总结
Kotlin 的 Preconditions
工具函数虽小,但在日常开发中极为实用。合理区分 require
/ check
及其 NotNull
变体,不仅能提升代码可读性,也更符合 Kotlin 的编程范式。
函数名 | 异常类型 | 推荐使用场景 |
---|---|---|
require() |
IllegalArgumentException |
参数校验 |
check() |
IllegalStateException |
内部状态检查 |
requireNotNull() |
IllegalArgumentException |
参数非空断言 |
checkNotNull() |
IllegalStateException |
状态相关引用非空检查 |
error() |
IllegalStateException |
主动中断流程,抛出致命错误 |
所有示例代码已整理至 GitHub:https://github.com/baeldung/kotlin-tutorials/tree/master/core-kotlin-modules/core-kotlin-7