Kotlin 泛型类型参数
Kotlin Generics type parameters
在下面的源代码
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)
}
函数addInt
和addAnotherInt
将Number
的逆变MutableList
作为参数。但是在 main
函数中,一行可以正常编译,而另一行则不能。
我还检查了这些函数生成的 java 代码,它们看起来完全相同。
函数 addInt
和 addAnotherInt
之间可能有什么区别?
in Number
表示“Number
或其超类型”。 Int
不是“Number
或其超类型”,而是其子类型。
简而言之,您声明您的 addAnotherInt()
想要一个至少与接受任何类型的 Number
.
一样通用的列表
相比之下,addInt
声明了 item: T
和 list: 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>
。
在下面的源代码
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)
}
函数addInt
和addAnotherInt
将Number
的逆变MutableList
作为参数。但是在 main
函数中,一行可以正常编译,而另一行则不能。
我还检查了这些函数生成的 java 代码,它们看起来完全相同。
函数 addInt
和 addAnotherInt
之间可能有什么区别?
in Number
表示“Number
或其超类型”。 Int
不是“Number
或其超类型”,而是其子类型。
简而言之,您声明您的 addAnotherInt()
想要一个至少与接受任何类型的 Number
.
相比之下,addInt
声明了 item: T
和 list: 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>
。