Kotlin 泛型类型参数



在以下源代码中

fun main(args: Array<String>) {
    println("Hello, world!")
    val mutableIntList = mutableListOf(1, 2, 3)
    addInt(4, mutableIntList) // No compile-time error
    addAnotherInt(5, mutableIntList) // Compile-time error
    println(mutableIntList)
}
fun <T: Number> addInt(item:T,
                       list:MutableList<in T>){
    list.add(item)
}
fun <T: Number> addAnotherInt(item:T,
                              list:MutableList<in Number>){
    list.add(item)
}

函数addIntaddAnotherIntNumber的逆变MutableList作为参数。但是在main函数中,一行正常编译,另一行则不正常。

我还检查了从这些函数生成的 java 代码,它们看起来是相同的。

addIntaddAnotherInt函数之间有什么区别?

in Number的意思是"Number或其超类型"。 Int不是"Number或其超型",而是它的子型。

简而言之,您声明您的addAnotherInt()想要一个至少与接受任何类型的Number一样通用的列表。

相比之下,addInt声明item: Tlist: MutableList<in T>T本身被声明为函数的自由类型变量,这意味着它将绑定在每个特定的调用站点。所以当你说

addInt(4, mutableIntList)

Kotlin 基于第一个参数将T绑定到Int,并将其传播到第二个参数,现在已MutableList<in Int>。您传入了与该类型兼容的MutableList<Int>,因此 Kotlin 感到满意。

如果您声明

val mutableIntList: MutableList<Number> = mutableListOf(1, 2, 3)

然后代码将编译,因为现在列表根据需要通用,您可以向其添加任何Number

您的代码将使用数字列表进行编译:

val mutableIntList = mutableListOf<Number>(1, 2, 3)

但是由于类型被推断为MutableList<Int>,所以不能将其用作MutableList<in Number>。这转换为 Java 等效MutableList<? super Number>,意味着您可以将任何Number添加到列表中。但是不可能在MutableList<Int>中添加Long

您的第二种方法addInt()更严格一些,可以在您的用例中转换MutableList<? super Int>。因此,您可以这样使用它。不过,这两种方法都能够使用MutableList<Number>

最新更新