Spring Boot中如何禁用特定Kotlin数据类构造参数的自动空检查?
解决Kotlin Spring Boot请求类非空校验与空安全冲突问题
这里有几种局部处理的方案,无需全局禁用Kotlin的空检查:
方案1:用抑制注解消除非空断言提示
直接在字段、类或者使用该字段的函数上添加@Suppress("UNNECESSARY_NOT_NULL_ASSERTION")注解,局部消除IDE和编译器对!!的多余提示:
加在字段上
data class SomeRequest( @field:NotNull @Suppress("UNNECESSARY_NOT_NULL_ASSERTION") val someField: String? ) @RestController class SomeController { @PostMapping(value = ["/something"]) fun something(@RequestBody @Valid someRequest: SomeRequest) { someRequest.someField!! } }
加在使用字段的函数上
data class SomeRequest( @field:NotNull val someField: String? ) @RestController class SomeController { @PostMapping(value = ["/something"]) @Suppress("UNNECESSARY_NOT_NULL_ASSERTION") fun something(@RequestBody @Valid someRequest: SomeRequest) { someRequest.someField!! } }
方案2:封装非空访问属性
在data class中定义一个额外的非空属性,将原字段设为私有,外部直接访问非空属性即可彻底摆脱!!:
data class SomeRequest( @field:NotNull private val _someField: String? ) { // 依赖Spring校验保证_someField非空,此处断言安全 val someField: String get() = _someField!! } @RestController class SomeController { @PostMapping(value = ["/something"]) fun something(@RequestBody @Valid someRequest: SomeRequest) { // 直接使用非空属性,无需断言 val value = someRequest.someField } }
这个方案既保留了Spring的非空校验,又避开了Kotlin构造函数的自动空检查,外部代码完全感知不到空类型的存在。
方案3:用Kotlin契约强化空安全推断
借助Kotlin实验性契约特性,告诉编译器该字段在校验通过后一定非空,让编译器自动推断类型:
import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract data class SomeRequest( @field:NotNull val someField: String? ) @OptIn(ExperimentalContracts::class) fun SomeRequest.getSomeField(): String { contract { returns() implies (this@getSomeField.someField != null) } return someField!! } @RestController class SomeController { @PostMapping(value = ["/something"]) fun something(@RequestBody @Valid someRequest: SomeRequest) { // 调用函数后,编译器自动推断返回值非空 val value = someRequest.getSomeField() } }
注意该特性为实验性,需要添加@OptIn(ExperimentalContracts::class)注解启用。
内容的提问来源于stack exchange,提问作者Jezor
相关产品推荐
相关产品推荐

