为了账号安全,请及时绑定邮箱和手机立即绑定

【备战春招】第13天 深入理解Kotlin泛型

标签:
Kotlin

课程名称:移动端架构师


课程章节:Android必备Kotlin核心技术


课程讲师:CrazyCodeBoy LovelyChubby


课程内容:

目录

  • 泛型接口/类(泛型类型)

  • 泛型字段

  • 泛型方法

  • 泛型约束

  • 泛型中的out与in

泛型接口/类(泛型类型)

定义泛型类型,是在类型名之后、主构造函数之前用尖括号括起的大写字母类型参数指定:

泛型接口

Java:

//泛型接口
interface Fruit<T> {
    T taste();
    void price(T t);
}

Kotlin:

//泛型接口
interface Fruit<T> {
    fun taste(); T
    void price(t: T)
}

泛型类

Java

abstract class Color<T> {
    T t;
    abstract void printColor();
}
class Blue {
    String color = "blue";
}
class BlueColor extends Color<Blue> {
    public BlueColor(Blue t) {
        this.t = t;
    }
    @Override
    public void printColor() {
        System.out.println("color:" + t.color);
    }
}

Kotlin

abstract class Color<T>(var t: T/*泛型字段*/) {
    abstract fun printColor()
}

class Blue {
    val color = "blue"
}

class BlueColor(t: Blue) : Color<Blue>(t) {
    override fun printColor() {
        println("color:${t.color}")
    }

}

泛型字段

定义泛型类型字段,可以完整地写明类型参数,如果编译器可以自动推定类型参数,也可以省略类型参数:

abstract class Color<T>(var t: T/*泛型字段*/) {
    abstract fun printColor()
}

泛型方法

Kotlin 泛型方法的声明与 Java 相同,类型参数要放在方法名的前面:

Java

public static <T> T fromJson(String json, Class<T> tClass) {
    T t = null;
    try {
        t = tClass.newInstance();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return t;
}

Kotlin

fun <T> fromJson(json: String, tClass: Class<T>): T? {
    /*获取T的实例*/
    val t: T? = tClass.newInstance()
    return t
}

泛型约束

Java 中可以通过有界类型参数来限制参数类型的边界,Kotlin中泛型约束也可以限制参数类型的上界:

Java

public static <T extends Comparable<? super T>> void sort(List<T> list){}

Kotlin

fun <T : Comparable<T>?> sort(list: List<T>?){}
sort(listOf(1, 2, 3)) // OK,Int 是 Comparable<Int> 的子类型
//    sort(listOf(Blue())) // 错误:Blue 不是 Comparable<Blue> 的子类型

对于多个上界的情况

//多个上界的情况
fun <T> test(list: List<T>, threshold: T): List<T>
        where T : CharSequence,
              T : Comparable<T> {
    return list.filter { it > threshold }.map { it }
}

所传递的类型T必须同时满足 where 子句的所有条件,在上述示例中,类型 T 必须既实现了 CharSequence 也实现了 Comparable

泛型中的out与in

在Kotlin中out代表协变in代表逆变,为了加深理解我们可以将Kotlin的协变看成Java的上界通配符,将逆变看成Java的下界通配符

//Kotlin使用处协变
fun sumOfList(list: List<out Number>)

//Java上界通配符
void sumOfList(List<? extends Number> list)

//Kotlin使用处逆变
fun addNumbers(list: List<in Int>)

//Java下界通配符
void addNumbers(List<? super Integer> list)

总结

Java 泛型Java 中代码示例Kotlin 中代码示例Kotlin 泛型
泛型类型class Box<T>class Box<T>泛型类型
泛型方法<T> T fromJson(String json, Class<T> tClass)fun <T> fromJson(json: String, tClass: Class<T>): T?泛型函数
有界类型参数class Box<T extends Comparable<T>class Box<T : Comparable<T>>泛型约束
上界通配符void sumOfList(List<? extends Number> list)fun sumOfList(list: List<out Number>)使用处协变
下界通配符void addNumbers(List<? super Integer> list)fun addNumbers(list: List<in Int>)使用处逆变

总的来说,Kotlin 泛型更加简洁安全,但是和 Java 一样都是有类型擦除的,都属于编译时泛型


KotlinGeneric.kt

package com.demon.kotlin

fun main() {
    println(Coke().taste().price)
    testSort()
}

/**
 * Generic 泛型
 * 泛型接口
 */
interface Drinks<T> {
    fun taste(): T
    fun price(t: T)
}
class Sweet {
    val price = 5
}
class Coke: Drinks<Sweet> {
    override fun taste(): Sweet {
        println("Sweet")
        return Sweet()
    }

    override fun price(t: Sweet) {
        println("Coke price: ${t.price}")
    }

}

/**
 * 泛型类
 * BlueColor(Blue()).printColor()
 */
abstract class Color<T>(var t: T /*泛型字段*/) {
    abstract fun printColor()
}
class Blue {
    val color = "blue"
}
class BlueColor(t: Blue): Color<Blue>(t) {
    override fun printColor() {
        println("color:${t.color}")
    }
}

/**
 * 泛型方法
 */
fun <T> fromJson(josn: String, tClass: Class<T>): T? {
    //获取T的实例
    val t: T? = tClass.newInstance()
    return t;
}

/**
 * 泛型约束
 * :表示上界,T extends Comparable<T>?
 */
fun <T: Comparable<T>?> sort(list: List<T>?){}
fun testSort() {
    sort(listOf(1, 2, 3, 4))    //OK, Int 是Comparable<Int>的子类型
//    sort(listOf(Blue())) // 错误,Blue不是Comparable<Blue>的子类型

    val listString = listOf("A", "B", "C")
    val list = testa(listString, "B")
    println(list)
}

/**
 * 多个上界的情况
 * 所传递的类型T必须同时满足 where 子句的所有条件,在上述示例中,类型 T 必须既实现了 CharSequence 也实现了 Comparable。
 */
fun <T> testa(list: List<T>, threshold: T): List<T>
        where T : CharSequence,
              T : Comparable<T> {
        return list.filter { it > threshold }.map { it }
}


/**
 * 泛型中的out与in
 */
// Kotlin使用处协变 = Java上界通配符: void sumOfList(List<? extends Number> list)
fun sumOfList(list: List<out Number>) {}
//Kotlin使用处逆变 = Java下界通配符: void addNumbers(List<? super Integer> list)
//fun addNumbers(list: List<in Int>) {}




课程收获:

谢谢老师,这一章学习kotlin泛型的使用,期待后边的继续学习。


https://img1.sycdn.imooc.com/63f2dee500017af314750875.jpg


https://img3.sycdn.imooc.com/63f2def10001bc5614010811.jpg




点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
移动开发工程师
手记
粉丝
0
获赞与收藏
4

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消