Kotlin 泛型 型变、逆变、星号投影、reified、泛型上限

1. kotlin 定义泛型类


// 定义泛型类
open class GenericDemo<T>(open var field: T? = null)

// 继承泛型类
class SubGeneric(param: Float) : GenericDemo<Float>() {
    override var field: Float? = param
}

fun main() {
 	val demo1 = GenericDemo<String>("demo1")
    val demo2 = GenericDemo<Int>(2)
    val demo3 = GenericDemo(true)
    val demo4 = SubGeneric(3.14f)

    println("${demo1.field}, ${demo2.field}, ${demo3.field}, ${demo4.field}") // demo1, 2, true, 3.14
}

2. kotlin 定义类型变

kotlin 使用 out 定义型变。即向外提供的类型,不能向其写入,同 java 的通配符上限


// name 只能用 val 声明,否则会有 setter 方法向其写入
class Fruit<out T>(private val name: T) {
    fun getFruitName(): T {
        return name
    }
}

fun main() {
	val apple = Fruit("apple")
	
	// Fruit<String> 可以被赋值给 Fruit<Any>
	val fruit: Fruit<Any> = apple
	println(fruit.getFruitName())
}

3. kotlin 定义类逆变

kotlin 使用 in 定义逆变。即向里写入的类型,不能向外提供,同 java 通配符下限


class Reverse<in T> {
    fun setValue(value: T) {
        println("value: $value")
    }
}

fun main() {
	var reverse1 = Reverse<Int>()
	val reverse2 = Reverse<Number>()
	reverse2.setValue(3.14f) // value: 3.14
	
	// 可以将 Reverse<Number> 赋值给 Reverse<Int>
	reverse1 = reverse2
}

4. kotlin 定义调用处型变

在调用原本不支持型变的类时,如 ArrayList,可以在使用时用 out 修饰泛型支持型变


fun main() {
 	var arrNumber: ArrayList<out Number> = arrayListOf(1, 0.2, 3f)
    val arrayInt: ArrayList<Int> = arrayListOf(1, 2, 3)
    
    // arrNumber 可以接受元素为 Int 类型集合
    arrNumber = arrayInt
    println(arrNumber) // [1, 2, 3]
}

5. kotlin 定义调用处逆变

在调用原本不支持型变的类时,如 ArrayList,可以在使用时用 in 修饰泛型支持逆变


fun main() {
 	var arrInt: ArrayList<in Int> = arrayListOf(1, 2, 3)
    val arrNum: ArrayList<Number> = arrayListOf(1, 0.2, 3f)
    
    // arrInt 可以接受元素为 Number 类型集合
    arrInt = arrNum
    println(arrInt) // [1, 0.2, 3.0]
}

6. kotlin 星号投影


fun main() {
	// val list : ArrayList = arrayListOf(1, 2, 3) // 编译错误
    // 使用 * 号,等价于 out Any? 可接受任意类型的元素
    val list1: ArrayList<*> = arrayListOf(1, 0.2, "3")
    val list2: ArrayList<out Any?> = arrayListOf(1, 0.2, "3")
    println("list1: $list1, list2: $list2") // list1: [1, 0.2, 3], list2: [1, 0.2, 3]
}

7. kotlin 定义泛型函数


fun <T> printSelf(param: T) {
    println(param)
}  

8. kotlin 使用 reified 修饰泛型

使用 reified 修饰 泛型后,可以将泛型变成具体化的类型(泛型具型化),从而可以使用其相关方法


inline fun <reified T> printSelfName() {
    val name = T::class.simpleName
    println("class simple name: $name")
}

fun main() {
 	printSelfName<Int>() // class simple name: Int
    printSelfName<String>() // class simple name: String
}

9. kotlin 定义泛型上限


// 定义类泛型上限
class Container<T : Number>(var param: T)

// 定义方法泛型上限
fun <T : Number> sum(vararg param: T) {
    var sum = 0.0
    param.forEach {
        sum += it.toDouble()
    }
    println("求和: $sum")
}
    
fun main() {
    val c1 = Container<Int>(1)
    val c3 = Container<Long>(3L)
    val c4 = Container<Float>(3.14f)
    
	sum(1, 2f, 3.0) // 求和: 6.0
}

// 类泛型指定多个上限
class Test<T>() where T : Callable<T>, T : Runnable {}

// 方法泛型指定多个上限
fun <T> func(param: T) where T : Callable<T>, T : Runnable {}
    

附 Github 源码:

TestGeneric.kt

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>