关于Kotlin可空类型扩展函数与智能转换差异的技术疑问
为什么标准库isNullOrBlank()和自定义nullOrBlank()调用后类型推断不同?
核心原因:标准库函数用了Kotlin契约(Contract)
Kotlin的契约机制允许函数向编译器传递额外的类型推断逻辑。标准库中的isNullOrBlank()函数带有@Contract注解,明确告知编译器:如果该函数返回false,那么调用它的String?类型接收者一定不为null。标准库的简化实现逻辑如下:
@kotlin.internal.InlineOnly @Contract("null -> true") public inline fun CharSequence?.isNullOrBlank(): Boolean { return this == null || this.isBlank() }当你写
if (!input.isNullOrBlank())时,编译器通过契约信息直接推断出此时input已转为非空的String类型,因此可以直接访问input.length,无需安全调用或非空断言。自定义函数缺少契约注解
你自己编写的nullOrBlank()函数默认没有添加契约注解,即便逻辑和标准库完全一致,编译器也无法从函数返回值推断出接收者的非空性。此时编译器仍将input视为String?类型,所以访问input.length时会触发编译错误,要求你使用?.或!!.。若想让自定义函数实现同样的效果,只需给它加上契约注解:
@Contract("null -> true") fun String?.nullOrBlank(): Boolean { return this == null || this.isBlank() }添加注解后,编译器就能识别出函数返回
false时接收者非空,此时访问input.length就不会报错了。
内容的提问来源于stack exchange,提问作者sh1mj1
相关产品推荐
相关产品推荐

