10. 泛型
2022年5月15日
10. 泛型
泛型是一种编译时的安全检测机制,它允许在定义类,接口,方法时使用类型参数,声明的类型参数在使用时,用具体的参数替换。
1. 类型参数
容器类的类型参数
class SmartList<T> :ArrayList<T>(){
fun find(t:T) :T?{
val index = super.indexOf(t)
return if(index!=-1) super.get(index) else null
}
}
fun main() {
val smartList = SmartList<String>()
smartList.add("赵思琦")
val find = smartList.find("赵思琦")
println(find)
}
扩展函数实现同样的功能
fun <T> ArrayList<T>.find(t:T):T?{
val index=this.indexOf(t)
return if(index!=-1) this[index] else null
}
fun main() {
val array = ArrayList<String>()
array.add("赵思琦")
val find = array.find("赵思琦")
println(find)
}
2. 泛型的不同限制
<T>
2.1 类名任意类型都可作为该类的类型参数
class Entity<T> {
}
fun main() {
val string = Entity<String>()
val int = Entity<Int>()
val double = Entity<Double>()
}
只要你愿意,你可以传任意多的类型参数进来
class Entity<A,B,C,D> {
}
fun main() {
val data = Entity<String,Int,Double,Float>()
}
<T:上界>
2.2 2.2.1 上界限制
限制T的类型
class Entity<T:Collection<String>> {
}
Entity<MutableList<String>>()
abstract class Animal{}
class Dog:Animal(){}
class Entity<T:Animal>{}
fun main() {
Entity<Dog>()
}
2.2.2 将T限制为某个类,或某个接口
类只能有一个,接口可以有多个。
abstract class F{}
interface Canine{}
interface Fly{}
class Dog<T> where T:F,T:Canine ,T:Fly{
}
类名<out T>
2.3 在Java中为 ? extends 上界通配符
2.3.1 限制该类型在对象中只能被读取而不能被写入
abstract class Animal<out T>{
abstract fun getName():T
}
class Dog:Animal<String>(){
override fun getName(): String {
return "汪汪"
}
}
2.3.2 泛型的子类指向父类
注意:t的子类, 而不是类的子类
在java中,泛型的子类无法指向父类,泛型是不型变的
但是,使用out 可以去除这样的限制。 通常 我们把它叫做协变
class Dog<out T>{
}
fun main() {
val dog:Dog<Any> = Dog<String>()
}
类名<in T>
2.4 在Java中为 ? super 下界通配符
2.4.1 限制该类型只能被写入不能被读取
abstract class Animal<out T,in S>{
abstract fun getName(s:S):T
}
class Dog:Animal<String,Char>(){
override fun getName(char: Char): String {
return char.toString()
}
}
fun main() {
val dog = Dog()
val name = dog.getName('汪') //输入Char 返回String
}
2.5 星投影
2.5.1 out协变(型变)的情况下
class Dog<out T>{}
fun main() {
val dog:Dog<*> = Dog<String>()
}
Dog<*>
相当于 Dog<out T>
2.5.2 in逆变的情况下
class Dog<in T>{}
fun main() {
val dog:Dog<*> = Dog<String>()
}
Dog<*>
相当于 Dog<in Nothing>
2.5.3 不变情况下
class Dog<T>{
fun setDog(t:T){
}
}
fun main() {
val a:Dog<*> = Dog<Int>()
}
a:Dog<*>
相当于 Dog<out T>
+ Dog<in Nothing>
2.4.2 泛型的父类指向子类
class Dog<in T>{
}
fun main() {
val dog:Dog<String> = Dog<Any>()
}
3. 类型擦除
泛型信息只存在于代码编译阶段,进入JVM之前,于泛型类型相关的信息会被擦除掉。
如果指定了类型上限,那么在运行时会是上限的类型
如果未指定类型上限,那么在运行时会是Object
4. reified
检查一个对象是否是T(类型参数)
class Dog<T>{
inline fun <reified T> classTypeChecked(item:String){
if(item is T){
println("类型符合")
}
}
}
fun main() {
val dog = Dog<String>()
dog.classTypeChecked<String>("狗子")
}