(新) Kotlin搞起来 —— 5.泛型

标签: Kotlin

本文声明
本文由Coder-pig编写,想了解其他内容,可见Coder-Pig的猪栏
尊重作者劳动成果,未经本人授权,禁止转载!违者必究!
《Kotlin搞起来》系列目录地址:http://blog.csdn.net/coder_pig/article/details/72851862


PS:本来是想把泛型加到上一节的类与对象中的,后来发现Kotlin文档中对泛型的
介绍令人难以理解,而且很多小伙伴对Java中的泛型也是一知半解,所以还是把
泛型这一章抽取出来,顺便捋一捋一些概念性的东西。


Java泛型的引入

问题引入
集合框架能存储各种对象,但是取出对象的时候可能出现类型不兼容的异常,比如:
往集合中插入String和Integer的对象,取出的对象可能是String或Integer类型的,
如果不用instanceof()判断对象类型,再用对应类型的变量存储的话,就可能会发
ClassCastException(类型转换异常)
疑问
每次取元素都要进行判断,显得非常繁琐,能不能在创建的时候就指定元素类型?
让编译器负责检查添加元素的合法性?
回答
当然可以,jdk 1.5引入的泛型(Generice)能帮我们解决问题,将确定不变的类型参数化
从而保证集合中存储的元素类型都是同一种,而且所有的强转都是自动与隐式的,
从而提高了代码的重用率。


Java中泛型的使用

泛型类 :

泛型接口

泛型方法

注意事项

  • 1.泛型的类型参数只能是类类型,不能是简单数据类型(int那些);
  • 2.泛型可以有多个泛型参数;
  • 3.有时我们想让集合存取的元素为某个类子类或者父类而非特定一个类,可以使用
    extends和super进行约束,这个又称为有界类型,比如有个父类是People,然后他有
    几个子类,Student,Worker,Police,想允许People和他的三个子类都运行放到集合中,
    直接写成<T extends People>就可以了,这个称上界约束,而super则称下界约束。

Java假泛型实现原理

和C#中的泛型不同,Java和Kotlin中的泛型都是假泛型,实现原理就是:类型擦除(Type Erasure),
Java编译器在生成Java字节码种是不包含泛型中的类型信息的,使用泛型的时候加上的类型参数,
会在编译器编译的时候去掉,然后用其限定类型替换!

比如下述代码,获取到的类类型都是一样的(ArrayList)

因为编译时会用限定类型替换,所以如果这里我们用反射往一个Integer类型的List插入
String类型的参数是不会报错的:

PS:关于类型擦除更多内容可见:http://blog.csdn.net/lonelyroamer/article/details/7868820


Java泛型通配符的引入

先来看一段代码:

我们都知道在Java中Object类是所有类的默认父类,按理来说应该是可以转型的。
然而编译器却报错了:

这里我们假设没报错,这个时候如果我们往list2里添加一个整数:

假设也没报错,但是运行的时候肯定是会报ClassCastException错误的!
Java中的泛型是不型变的,意味着 List<String>并不是List<Object>的子类型,
Java以此方式来保证运行时的安全。为了解决这个问题,Java中又引入了泛型通配符:

<? extends E>

表示该方法只接受E或者E的子类,但不知道是哪个具体的子类型,所以只能读不能写
从而使得类型是协变的,又叫上界限定通配符。看到Collection接口里的addAll方法就了解了:

<? super E>

对应的逆变则是只能接受E或者E的父类,因为无法判断读取到的类型,所以只能写不能读
又叫下界限定通配符

<?>

最后还有个无限定通配符,类型完全位置,此时只能读不能写,这个叫不变


Kotlin中的型变

基本的泛型用法比较简单,和Java中的基本类似,难点还是型变,Kotlin中没有通配符类型,
但有其他两个东西:声明处型变(declaration-site variance)与 类型投影(type projections)。

声明处型变

在Java里,如果你写这样一段代码,编译器是不会通过的:

按照我们的理解来说,上面的代码应该是没问题的,但是编译器不知道,仍然禁止这样的操作,
我们可以声明通配符对象类型为:

使用了更复杂的类型并没有任何意义,依旧可以调用对象的所有相同的方法,编译器依旧不知道。
Kotlin中,有一种方法向编译器解释这种情况,称为声明处型变。使用到的修饰符是:inout

out协变,只能用作输出,可以作为返回值类型,但无法作为入参类型

输出结果

in逆变,只能用作输入,可以作为如残类型,但无法作为返回值类型

类型投影

使用处型变,有些类实际上不能限制为只返回T,该类在T上既不能是协变的也不能是逆变的,
然后根据不同的方法,你可以使用in 或 out进行限制,比如:

fun copy(from: Array<out Any>, to: Array<Any>) { /* …… */ }
fun fill(dest: Array<in String>, value: String) { /* …… */ }

*投影

和Java中的?通配符类似,Kotlin可以根据 * 所指代的泛型参数进行相应的映射,官方解释如下:

  • 对于 Foo <out T>,其中 T 是一个具有上界 TUpper 的协变类型参数,Foo < * > 等价于 Foo <out TUpper>。这意味着当 T 未知时,你可以安全地从 Foo <*> 读取 TUpper 的值。
  • 对于 Foo <in T>,其中 T 是一个逆变类型参数,Foo < * > 等价于 Foo <in Nothing>。
    这意味着当 T 未知时,没有什么可以以安全的方式写入 Foo < * >。
  • 对于 Foo <T>,其中 T 是一个具有上界 TUpper 的不型变类型参数,Foo< * > 对于读取值时等价于
    Foo<out TUpper> 而对于写值时等价于 Foo<in Nothing>。

注意事项:

  • 不允许作为函数和变量的类型的泛型参数!
  • 不允许作为函数和变量的类型的泛型参数!
  • 不能直接作为父类的泛型参数传入!

PS:关于Kotlin中泛型最后的几点我还是有点模糊的,实际开发没用过,体会不够深刻,等以后
用到了有所收获后再来对这部分重新编辑~


本文参考文献:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容