这节我们说下Kotlin的泛型。首先默认大家对Java泛型有个基本的认识,如果 不熟悉Java的泛型,可以阅读文章,或是看下Java《Java核心技术卷一基础知识第10版》中关于泛型章节的知识,讲述的也很详细。其实Kotlin的泛型和Java很相似。他们都是伪泛型,所谓伪泛型就是我们们是无法获取到泛型的具体的类型的。以为Java存在类型擦除和转换。本篇还是和反射一样,从实际代码编写角度,说下Kotlin的泛型
泛型的逆变与协变其其在Java中也有。简单概括来说就是<? extends T>实现了泛型的协变,<? super T>实现了泛型的逆变。具体的这两种有什么特性可以看开头两篇文章。
代码示例:
val listOf: List<Number> = listOf<Int>(1, 2, 3)
在泛型参数前面加上out表示协变,作为返回值,为只读类型, 它的子类的泛型参数的类型是父类的泛型参数类型的子类,也就是说泛型参数的继承关系与类的继承关系保持一致(所以叫协变),比如Number是Int的父类 那么List<Number>也是List<Int>父类型;
val value: Comparable<Int> = object : Comparable<Any> {
override fun compareTo(other: Any): Int {
return 0
}
}
在泛型参数前面加上in表示逆变,作为传入的参数,为只写类型,它的泛型参数的继承关系与类的继承关系相反,比如父类是Any,子类是Int。
val mutableList: MutableList<Int> = mutableListOf<Int>(1, 2, 3)
val listOf1: List<Number> = listOf(1, 2, 3)
//这是可以的
val listOf2: List<*> = listOf(1, 2, 3)
// val listOf3: List<Number> = listOf<*>(1, 2, 3)//ERROR
//这是可以的
val value1: Comparable<*> = object : Comparable<Any> {
override fun compareTo(other: Any): Int {
return 0
}
}
//可以
val value2: Comparable<*> = object : Comparable<Int> {
override fun compareTo(other: Int): Int {
return 0
}
}
//不可以
// val value3: Comparable<Int> = object : Comparable<*> {//error
// override fun compareTo(other: Int): Int {
// return 0
// }
// }
// val hello=Hello<*>//ERROR 因为泛型实参时不能用*代替
//java 是可以有弱类型的(目的是兼容1.5) Kotlin不可以 定义了泛型了 创建的时候就必须指定泛型
星投影只能只能作为形参,不能作为实参。
reified单词含义为具体化的。用法
inline fun <reified T> testGenerics2() {
println(T::class.java)
}
加上reified关键字就可以打印出来他的类型了,这是在Java中做不到的。
inline表示内联函数
其实泛型很难讲清楚。就算讲清楚了,也可能晦涩难懂。其实泛型掌握了编写规则。多实践,就好了。下篇讲下Kotlin的协程