【问题标题】:Kotlin Map/List Nullable Type SafetyKotlin Map/List 可空类型安全
【发布时间】:2023-03-04 13:19:01
【问题描述】:

我是 kotlin 新手,所以我的问题需要一些关键字。

这是我的 kotlin 代码:

fun foo(map: Map<String, Int>) {
  map.forEach {
    println(it.value.toString())
  }
}

这个 sn-p 在调用时会导致 NPE,如下所示:

fun main() {
  val map = mapOf("bar" to null) as Map<String, Int>
  foo(map)
}
  1. 我不知道为什么这个转换 mapOf("bar" to null) as Map&lt;String, Int&gt; 没有编译错误。
  2. 不知道为什么函数 foo 在没有编译错误或警告或 !! 时会导致 NPE

我确定有类似的问题,但我找不到问题或任何关键词。


其实我用的是这张地图:

val objectMapper = jacksonObjectMapper()
val string = """ 
    { "value": null }
""".trimIndent()
// this is an example, origin string comes from RESTAPI input.
val convertedMap: Map<String, String> = objectMapper.readValue(string)

它没有发出任何警告,它导致了 NPE。 我需要一些使用 kotlin Map/List 的提示,以免出现意外错误。

【问题讨论】:

  • 你会收到一个警告,告诉你这是一个不安全的演员阵容。
  • 虽然readValuesuppressWarnings..

标签: kotlin type-safety


【解决方案1】:

铸造本质上是不安全的。你告诉编译器你比编译器更了解你正在转换的对象。在某些情况下,编译器会在转换时给你一个错误,当它可以告诉你正在转换的东西不可能与其他类型匹配时。

当您强制转换为没有泛型的类时,您通常根本不会收到任何警告。假设就像!! 一样,如果你在铸造,你知道你在做什么。您已经检查了可能的逻辑,并且可以绝对确认强制转换是安全的,即使编译器无法判断。

当你使用泛型转换为一个类时,编译器至少会给你一个警告。这是因为如果泛型类型错误,转换不会失败。由于类型擦除,它会成功,然后当您开始与对象交互时,您会在代码的其他地方收到错误。所以出现警告是因为它比 ClassCastException 更糟糕,因为导致的错误发生在代码中的其他地方,而不是执行转换的行,这使得调试变得更加困难。

抑制警告只会使警告消失。它根本不会改变行为。仅当您检查了警告可能导致的故障并确定您正在执行的操作是安全的时,才取消显示警告。

对于您的 Map,尽管它包含空值,但将其转换为不可为空的值将在运行时成功,但稍后在您检索值时失败。

【讨论】:

    猜你喜欢
    • 2018-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-02
    • 2020-01-03
    • 1970-01-01
    • 2013-10-14
    相关资源
    最近更新 更多