【问题标题】:Why can't Kotlin implicitly upcast Array of String into Array of Any?为什么 Kotlin 不能将字符串数组隐式向上转换为任意数组?
【发布时间】:2020-01-23 22:34:33
【问题描述】:

以下代码将 String 隐式向上转换为 Any。

    val s = "some string"
    val upcasted: Any = s

但是,以下内容无法编译(类型不匹配):

    val s = arrayOf("some string")
    val upcasted: Array<Any> = s

你可以成功投到Array&lt;Any&gt;如图:

    val s = arrayOf("some string")
    val upcasted: Array<Any> = s as Array<Any>

但是,这会发出警告 "Unchecked cast: Array&lt;String&gt; to Array&lt;Any&gt;"。 相同的逻辑确实似乎适用于列表,那么 Array 的内部实现与这种类型的转换不兼容吗?也许是因为数组的内存表示?

【问题讨论】:

标签: arrays generics kotlin casting any


【解决方案1】:

您不能像这样安全地将类型转换为超类型或子类型,因为Array&lt;String&gt; 不符合Array&lt;Any&gt; 的条件。如果你试图在你假设的Array&lt;Any&gt; 中放置一个 Double,它会抛出一个异常,因为实际类型是一个字符串数组。数组是没有类型擦除的泛型的一种特殊情况,因此它们被锁定为它们被实例化的类型。

您可以将其转换为Array&lt;out Any&gt;,因为您可以通过这种方式安全地使用它。您可以将字符串 out 从数组中拉出,它们可以作为 Any 的实例。反过来是不正确的。您不能将 Any 的任何实例及其子类放入 String 数组中。

当涉及到 List 时,您可以将其转换为具有超类型类型的 List,甚至不必手动转换它。它是安全的,所以可以隐式地完成演员阵容。

val s = listOf("some string")
val upcasted: List<Any> = s // implicit cast

那么你为什么不强制转换为List&lt;out Any&gt;? List 接口没有任何允许您向其中添加内容的功能。它在其声明中使用out-projected 类型定义,因此当您键入List&lt;Any&gt; 时,它已经与List&lt;out Any&gt; 相同

如果您尝试使用 MutableList 执行此操作,该列表接受将项目放入其中并且未使用 out-projected 类型定义,那么您将遇到与数组相同的警告。

val s = mutableListOf("some string")
val upcasted: MutableList<Any> = s as MutableList<Any> // warning here and implicit cast impossible

this 和 Array 的区别在于有类型擦除,所以如果你尝试在这个列表中添加一些非字符串,你不会有运行时异常。但是如果你不小心,可能会出现隐藏的错误,因此会发出警告。

【讨论】:

  • 感谢您的解释! List vs MutableList 非常有趣。多年来我在 Java 中也遇到过类似的问题,直到现在才完全理解。
猜你喜欢
  • 2013-04-02
  • 2018-09-27
  • 2021-02-04
  • 1970-01-01
  • 2017-04-09
  • 2011-03-24
  • 1970-01-01
  • 2017-03-11
  • 1970-01-01
相关资源
最近更新 更多