为什么 Kotlin 不能隐式地将字符串数组转换为任意数组?

Why can't Kotlin implicitly upcast Array of String into Array of Any?

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

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

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

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

您可以成功转换为 Array<Any>,如图所示:

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

然而,这给出了警告"Unchecked cast: Array<String> to Array<Any>"。 同样的逻辑似乎也适用于列表,那么数组的内部实现是否与这种类型的转换不兼容?也许是因为数组在内存中的表示?

您不能像这样安全地将类型转换为超类型或子类型,因为 Array<String> 不符合 Array<Any> 的条件。如果您尝试将 Double 放入假定的 Array<Any> 中,它会引发异常,因为实际类型是 String 数组。数组是泛型的一种特殊情况,没有类型擦除,因此它们被锁定为实例化时使用的类型。

您可以将其转换为 Array<out Any>,因为您可以安全地使用它。您可以从数组中提取字符串 out,它们符合 Any 的实例。反之则不然。您不能将 Any 及其子类的任何实例放入 String 数组中。

对于List,你可以将它转换为超类型的List,甚至不需要手动转换。它是安全的,因此可以隐式完成转换。

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

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

相同

如果您尝试使用 MutableList 执行此操作,它接受将项目放入其中并且未使用 out 投影类型定义,那么您将 运行 进入与您相同的警告对数组做了。

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

它与 Array 的区别在于存在类型擦除,因此如果您尝试向该列表添加一些非字符串,则不会出现 运行time 异常。但是一不小心就有可能隐藏bug,所以警告。