Kotlin-扩展功能和平台类型?

Kotlin- Extension functions and platform types?

我想向 ResultSet 添加两个扩展函数,它们获取一个值作为 LocalDate

fun ResultSet.getLocalDate(colName: String) = getDate(colName)?.toLocalDate()
fun ResultSet.getLocalDate(colIndex: Int) = getDate(colIndex)?.toLocalDate()

问题是 getDate() returns 一个 Date!,显然如果 toLocalDate() 之前没有 ?. 调用,我可能会得到一个空错误。但是任何使用此扩展的人都必须将结果用作 LocalDate? 而不是 LocalDate!

有什么方法可以保持平台类型的一致性?并让扩展功能的用户决定是否允许为空?或者我是否将此错误地视为一种不便而不是一种功能?

从不同的角度来看:如果您可以使您的函数 return 成为平台类型 LocalDate! 的值,Java 不安全的可空性将传播到您的函数用法中Kotlin 代码:它们会在任何时候 return null,这可能是使用 return 值作为非空值的调用者意想不到的。

Kotlin 反过来,is null-safe 并且它不允许将 null 静默传递到会导致 NPE 的地方。相反,每个值要么作为可空值传递,要么通过非空检查或断言。

Platform types are non-denotable in the language, this is just a way of dealing with unsafe Java nullability (simply treating all Java values as nullable wouldn't work)。它们为您提供了一种方式来声明您 相信对 Java 代码的调用不会 return null:当您将 T! 视为 T,生成一个断言来检查它。否则,您使用的平台类型 T! 与可空 T?.

一样

null 安全是 Kotlin 语言设计的关键点之一,它让您决定 Kotlin 代码中的每个值是否可为 null。

API 设计有两种选择:

  • Return 一个非空值,检查函数内部的可空性
  • Return 可为 null 的值,因此警告调用者可能 null

但是,如果一个函数的语义允许调用者假设它在某些情况下不会 return null,您可以创建一个包装函数来进行断言。如果加上额外的逻辑或回退,这是可行的,否则它几乎不会比调用站点的断言(!!)更简洁。