Kotlin Generics类型参数

LiT*_*Tle 6 generics contravariance 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)
}
Run Code Online (Sandbox Code Playgroud)

的功能addIntaddAnotherInt采取作为自变量的逆变MutableListNumber.但是在main功能上,一行正常编译而另一行则不正常.

我还检查了这些函数生成的java代码,它们看起来完全相同.

可能是什么功能之间的差异addIntaddAnotherInt

Mar*_*nik 8

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

简单来说,你声明你addAnotherInt()想要的列表至少和接受任何类型的列表一样通用Number.

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

addInt(4, mutableIntList)
Run Code Online (Sandbox Code Playgroud)

科特林结合TInt基于所述第一参数和传播这第二个参数,这是现在MutableList<in Int>.你通过了MutableList<Int>与那种类型相容的,所以Kotlin很满意.

如果你声明了

val mutableIntList: MutableList<Number> = mutableListOf(1, 2, 3)
Run Code Online (Sandbox Code Playgroud)

那么代码就会编译,因为现在列表就像所需的那样一般,你可以添加任何代码Number.

  • 我尊重逆向的完美措辞,"至少像接受任何一种数字一样普遍". (3认同)