首页 > 解决方案 > Kotlin 泛型中列表和可变列表的区别

问题描述

我最近研究了 kotlin 泛型,但我发现了一些奇怪的情况

IDE 映像

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 情况下,编译器会警告未选中的 Cast

如果有人知道这种情况,请告诉我。

标签: kotlingenericsmutablelist

解决方案


List接口具有声明站点协方差( <out T>)。这意味着“向上转换”类型是安全的,因为 List 只输出项目。例如,如果您有 a List<Int>,则将其用作 a 是安全的,List<Number>因为 anInt始终可以安全地转换为 a Number。当您从列表中检索项目时,它们总是满足为 typeInt或 supertype Number

MutableList没有协变类型。它在声明站点是不变的。这意味着“向上转换”它的类型本质上是不安全的。例如,如果您将您的MutableList<Int>转换为 a MutableList<Number>,则使用该引用是不安全的 MutableList<Number>,因为它会让您将 a 添加Float到列表中。当原始引用用作 aMutableList<Int>并尝试从中检索值时,它将获得 ClassCastException 以尝试使用Floatas a Int

在这种情况下,您可以安全地将MutableList转换为协变类型,如下所示:

val castedItem = items as MutableList<out MyItem>?

但是MutableList具有协变类型的 a 与 a 并没有什么不同List,因此最好将其强制转换为 aList<MyItem>以使意图更清晰。


推荐阅读