Kotlin泛型中链表与可变链表的区别

6jygbczu  于 2023-01-02  发布在  Kotlin
关注(0)|答案(1)|浏览(114)

我最近研究了Kotlin仿制药,但是我发现了一些奇怪的构造
IDE image

interface MyItem

fun <ITEM : MyItem> bindItem(items: List<ITEM>?) {
    val castedItem = items as List<MyItem>?
}

fun <ITEM : MyItem> bindItem2(items: MutableList<ITEM>?) {
    val castedItem = items as MutableList<MyItem>?
}

仅在MutableList情况下编译器警告未选中的强制转换
如果有人知道这个情况,请告诉我.

lskq00tm

lskq00tm1#

List接口具有声明站点 * 协方差 *(<out T>)。这意味着“向上转换”类型是安全的,因为List只输出项。例如,如果您有List<Int>,则将其用作List<Number>是安全的,因为Int始终可以安全地转换为Number。从列表中检索项时,它们总是满足是类型Int或超类型Number
MutableList没有协变类型。它在声明位置为 invariant。这意味着“向上转换”其类型本身并不安全。例如,如果将MutableList<Int>转换为MutableList<Number>,则使用MutableList<Number>引用并不安全。因为它会让你把一个Float添加到列表中。当原始引用被用作MutableList<Int>并试图从中检索一个值时,它会因为尝试将Float用作Int而获得ClassCastException。
在这种情况下,可以安全地将MutableList强制转换为协变类型,如下所示:

val castedItem = items as MutableList<out MyItem>?

但是具有协变类型的MutableList实际上与List没有任何不同(除了可以clear()它之外),因此最好将它强制转换为List<MyItem>以使意图更清楚。

相关问题