Kotlin 提供了与 Java 的无缝互操作性,几乎不影响其自身的空安全性。一个例外是 Kotlin 假设allJava 中定义的类型不是 null。
为了理解,让我们看看JsonNode.get()
平台类型
public JsonNode get(String fieldName) { return null; }
注意JsonNode
是在 Java 中定义的,因此是平台类型 https://kotlinlang.org/docs/java-interop.html#null-safety-and-platform-types- Kotlin 不会将其“翻译”为JsonNode?
,即使这在技术上是正确的(因为在 Java 中所有类型都是可为空的)。
从 Kotlin 调用 Java 时,为了方便 https://discuss.kotlinlang.org/t/why-doesnt-kotlin-default-to-nullable-for-java-types/16753假设平台类型不可为空。如果不是这样的话,你会always必须检查任何平台类型的任何实例不为空。
因此,要回答您关于“平台类型”是什么的问题,这个术语的意思是
- 用外部目标语言定义的某种类型,
- 你不能在 Kotlin 代码中明确提及它(但可能有一个同义的 Kotlin 等效项),
- 为了方便起见,我们假设它是不可为空的。
- 记号也是
<type>!
, 例如String!
- 我们可以理解为String or String?
可空性注释
与 Kotlin 的 nullable 最接近的 Java 等价物?
符号是可空性注释 https://kotlinlang.org/docs/java-interop.html#nullability-annotations,Kotlin 编译器可以解析并考虑它。然而,没有一个被用于JsonNode
方法。所以 Kotlin 会很高兴地假设node.get("")
将返回JsonNode
, not JsonNode?
.
正如您所指出的,没有定义HashMap.get(...)
.
那么 Kotlin 如何知道这一点map.get("a")
返回可空类型?
类型推断
类型推断 https://kotlinlang.org/spec/type-inference.html#type-inference没办法。 (Java) 方法签名
public V get(Object key) {
//...
}
表明一个HashMap<String, String>
应该返回String
, not String?
。肯定还有其他事情发生...
映射类型
对于大多数 Java 类型,Kotlin 将仅使用所提供的定义。但对于某些,Kotlin 决定特殊对待它们,并用自己的版本完全替换 Java 定义。
你可以看到文档中映射类型的列表 https://kotlinlang.org/docs/java-interop.html#mapped-types。而同时HashMap
不在那里,Map
是。所以,当我们编写 Kotlin 代码时,HashMap
不继承自java.util.Map
- 因为它被映射到kotlin.collections.Map
Aside: in fact if you try and use java.util.Map
you'll get a warning
所以如果我们看一下代码get
功能是kotlin.collections.Map
定义,我们可以看到它返回一个可为空的值类型 https://github.com/JetBrains/kotlin/blob/6fc27c22f44d8051bf2e89f1657c0d9741c281c0/core/builtins/native/kotlin/Collections.kt#L320
/**
* Returns the value corresponding to the given [key], or `null` if such a key is not present in the map.
*/
public operator fun get(key: K): V?
所以 Kotlin 编译器可以查看HashMap.get(...)
并推断出这一点,因为它正在实施kotlin.collections.Map.get(...)
,返回值must是一个可为空的值,在我们的例子中是String?
.
解决方法:外部注释
无论出于何种原因,杰克逊没有使用可以解决此问题的可为空注释。幸运的是,IntelliJ 提供了一种解决方法,虽然不那么严格,但会提供有用的警告:外部注释 https://www.jetbrains.com/help/idea/external-annotations.html.
一旦我按照说明操作...
-
Alt+Enter → '注释方法...'
-
选择“可为空”注释
-
Save annotations.xml
Now node.get("")
将显示警告。
此注释对 Kotlin 编译器不可见,因此它只能是警告,而不是编译错误。