泛型允许定义带类型形参的类型,当这种类型的实例被创建出来的时候,类型形参被替换成称为类型实参的具体类型
实例
// 源码listOf函数声明 fun <T> listOf(vararg elements: T): List<T> val list=listOf("hello","world") // 编译器推导 val list= listOf<String>()// 显示说明上例中 T 为类型形参 ,并且函数的返回类型使用了类型形参
Kotlin 通过在类名称后加上一对尖对号,并把类型参数放在尖对号内来声明泛型类及泛型接口。一旦声明之后,就可以在类的主体内像其他类型一样使用类型参数。
// 泛型类 class Gen<T>(private var t: T) { fun getValue() :T{ return t } } // 泛型接口 interface List<T>{ public operator fun get(index: Int): T }小结: 如果类继承了泛型类(实现了泛型接口),就得为基础类型的泛型形参提供了一个类型实参,它可以是具体类型或者另一个类型形参:
class GenList:List<String>{ override fun get(index :Int):String=... } class ArrayList<T>:List<T>{ override fun get(index :Int):T=... }泛型函数有它自己的类型形参,这些类型形参在每次函数调用时都必须替换成具体的类型实参
fun <T> printMessage(msg :T){ when (content) { is Int ->{"该信息数据类型是整型"} else ->{"该信息数据类型不是整型"} } }注意: 普通(即非拓展)属性不能拥有类型参数,不能在一个类的属性中存储多个不同类型的值,因此声明泛型非拓展函数没有任何意义
类型参数约束可以限制作为泛型类和泛型函数的类型实参的类型;如果把一个类型指定为泛型类型形参的上界约束,在泛型类型具体的初始化中,其对应的类型实参就必须是这个具体类型或者它的子类型
示例
// 函数声明 fun <T:Number> List<T>.sum() :T // 具体类型实参继承了Number,函数调用是允许的 println(listOf(1,2,3).sum())上例中,通过在类型参数后指定上界来定义约束,把冒号放在类型参数名称之后,作为类型形参上界的类型紧随其后;一旦指定了类型形参T的上界,就可以把类型T的值当作它的上界(类型)的值使用
如果声明的是泛型类或者泛型函数,任何类型实参,包括那些可空的类型实参,都可以替换它的类型形参;没有指定上界的类型形参将会使用Any?这个默认上界
// 类型参数可空 默认上界的类型形参是Any? class Person<T>{ fun name(value :T){ value?.hashcode() } } // 类型参数非空 默认上界的类型形参是Any class Person<T:Any>{ fun name(value :T){ value?.hashcode() } }注意:可以通过指定任意非空类型作为上界,来让类型参数非空,不光是类型Any