前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Kotlin学习笔记(七)-泛型

Kotlin学习笔记(七)-泛型

作者头像
g小志
发布2019-12-19 21:24:50
6330
发布2019-12-19 21:24:50
举报
文章被收录于专栏:Android常用基础Android常用基础
前言

这节我们说下Kotlin的泛型。首先默认大家对Java泛型有个基本的认识,如果 不熟悉Java的泛型,可以阅读文章,或是看下Java《Java核心技术卷一基础知识第10版》中关于泛型章节的知识,讲述的也很详细。其实Kotlin的泛型和Java很相似。他们都是伪泛型,所谓伪泛型就是我们们是无法获取到泛型的具体的类型的。以为Java存在类型擦除和转换。本篇还是和反射一样,从实际代码编写角度,说下Kotlin的泛型

逆变与协变

泛型的逆变与协变其其在Java中也有。简单概括来说就是<? extends T>实现了泛型的协变,<? super T>实现了泛型的逆变。具体的这两种有什么特性可以看开头两篇文章。

Kotlin中的协变与逆变
  • 泛型参数即可作为传入的参数,也可以作为返回值,但被in和out关键字修饰后就不一样了
  • out 叫协变 只能作为返回值读取 不能写入和修改(Kotlin的list中只有get方法 没有add)
  • in 叫逆变 只能写入不能读取 只能作为参数传入 (Kotlin中的Comparable只能传入参数)
  • 不变 既没有in也没有out就叫做不变 如MutableList(相当于java中的list)
  • 协变点:返回值类型是泛型类型参数
  • 逆变点:入参类型是泛型参数的类型
  • @UnsafeVariance 型变点伪例(当时协变的时候 泛型作为参数入参会报错 那么如果我们想忽略这个错误那么我就可以用这个注解标识)

代码示例:

协变 :泛型类型与实参的类型的继承关系相同
代码语言:javascript
复制
   val listOf: List<Number> = listOf<Int>(1, 2, 3)

在泛型参数前面加上out表示协变,作为返回值,为只读类型, 它的子类的泛型参数的类型是父类的泛型参数类型的子类,也就是说泛型参数的继承关系与类的继承关系保持一致(所以叫协变),比如Number是Int的父类 那么List<Number>也是List<Int>父类型;

逆变 泛型参数的继承关系与类的继承关系相反
代码语言:javascript
复制
    val value: Comparable<Int> = object : Comparable<Any> {
        override fun compareTo(other: Any): Int {
            return 0
        }
    }

在泛型参数前面加上in表示逆变,作为传入的参数,为只写类型,它的泛型参数的继承关系与类的继承关系相反,比如父类是Any,子类是Int。

不变 类型必须保持一致 泛型之间没有关系
代码语言:javascript
复制
    val mutableList: MutableList<Int> = mutableListOf<Int>(1, 2, 3)
星投影 其本质就是类似Java中通配符 ?
代码语言:javascript
复制
 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 关键字

reified单词含义为具体化的。用法

代码语言:javascript
复制
inline fun <reified T> testGenerics2() {
    println(T::class.java)
}

加上reified关键字就可以打印出来他的类型了,这是在Java中做不到的。

inline关键字的作用

inline表示内联函数

  • inline 修饰符影响函数本身和传给它的 lambda 表达式:所有这些都将内联到调用处。
  • 内联可能导致生成的代码增加;不过如果我们使用得当(即避免内联过大函数),性能上会有所提升,尤其是在循环中的“超多态(megamorphic)”调用处。
  • inline关键字的作用是 一个方法带参数 同时这个方法中的参数是一个高阶函数(也就是Lambda表达式),那么inline可以提升性能

结语

其实泛型很难讲清楚。就算讲清楚了,也可能晦涩难懂。其实泛型掌握了编写规则。多实践,就好了。下篇讲下Kotlin的协程

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 逆变与协变
  • Kotlin中的协变与逆变
    • 协变 :泛型类型与实参的类型的继承关系相同
      • 逆变 泛型参数的继承关系与类的继承关系相反
        • 不变 类型必须保持一致 泛型之间没有关系
          • 星投影 其本质就是类似Java中通配符 ?
            • reified 关键字
              • inline关键字的作用
              • 结语
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档