Kotlin实现Spring的ResultSetExtractor因JSpecify泛型注解报错
我在Kotlin中尝试实现Spring的ResultSetExtractor接口时遇到了问题,根源在于Kotlin对Java泛型中T extends @Nullable Object的解析逻辑。当前使用的版本是Kotlin 2.3.21和Spring 7.0.7。
编写的代码示例
import org.springframework.jdbc.core.ResultSetExtractor import java.sql.ResultSet class CustomRSE<T> : ResultSetExtractor<T> { override fun extractData(rs: ResultSet): T? { return null } }
报错信息
return type of 'fun extractData(rs: ResultSet): T?' is not a subtype of the return type of the overridden member 'fun extractData(rs: ResultSet): T' defined in 'com.infobip.mdp.CustomRSE'.
这个结果明显不符合预期,目前找到的唯一临时解决方案是添加编译参数-Xjspecify-annotations=warn。
疑问与分析
这到底是Kotlin、Spring还是JSpecify的问题?看起来Kotlin是刻意忽略了该注解。
根据Kotlin官方文档的说明:
该注解不适用于……类型变量(泛型)。类型变量在被指定具体的可空或非可空类型前保持“空值无关”状态。
作为参考,Spring 7中ResultSetExtractor接口的Java定义如下:
@FunctionalInterface public interface ResultSetExtractor<T extends @Nullable Object> { /** * @return an arbitrary result object, or {@code null} if none * (the extractor will typically be stateful in the latter case). */ T extractData(ResultSet rs) throws SQLException, DataAccessException; }
问题的核心在于:Spring通过@Nullable注解声明了泛型类型T允许为空,但Kotlin不处理泛型类型变量上的JSpecify注解,因此在Kotlin看来,接口的extractData方法返回的是非可空的T,而我们实现时返回T?(可空)就会出现类型不匹配的错误。这属于Kotlin对JSpecify注解的处理规则限制,并非Spring或JSpecify的问题。
内容的提问来源于stack exchange,提问作者milan

