教你如何攻克Kotlin中泛型型变的难点(上篇)

本文深入探讨Kotlin中泛型型变的概念,包括为什么需要型变、类与类型的区别、子类型化关系等,并通过实例分析型变的重要性。了解型变有助于提高泛型接口的安全性和理解Kotlin的泛型系统。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简述:
Kotlin中泛型相关的文章也几乎接近尾声,但到后面也是泛型的难点和重点。相信有很多初学者对Kotlin中的泛型型变都是一知半解,比如我刚开始接触就是一脸懵逼,概念太多了,而且每个概念和后面都是相关的,只要前面有一个地方未理解后面的难点更是越来越看不懂。Kotlin的泛型比Java中的泛型多了一些新的概念,比如子类型化关系、逆变、协变、星投影的。个人认为学好Kotlin的泛型主要有这么几个步骤:

  • 第一,深入理解泛型中每个小概念和结论,最好能用自己的话表述出来;
  • 第二,通过分析Kotlin中的相关源码验证你的理解和结论;
  • 第三,就是通过实际的例子巩固你的理解;

由于泛型型变涉及的内容比较多,所以将它分为上下两篇,废话不多说请看以下导图:

一、为什么会存在型变?

首先,我们需要明确两个名词概念: 基础类型和实参类型。例如对于List<String>, List就是基础类型而这里的String就是实参类型

然后,我们需要明确一下,这里的型变到底指的是什么?

可以先大概描述一下,它反映的是一种特殊类型的对应关系规则。是不是很抽象?那就先来看个例子,例如List<String>和List<Any>他们拥有相同的基础类型,实参类型StringAny存在父子关系,那么是不是List<String>List<Any>是否存在某种对应关系呢? 实际上,我们讨论的型变也就是围绕着这种场景展开的。

有了上面的认识,进入正题为什么需要这种型变关系呢?来看对比的例子,我们需要向一个函数中传递参数。

fun main(args: Array<String>) {
   
   
    val stringList: List<String> = listOf("a", "b", "c", "d")
    val intList: List<Int> = listOf(1, 2, 3, 4)
    printList(stringList)//向函数传递一个List<String>函数实参,也就是这里List<String>是可以替换List<Any>
    printList(intList)//向函数传递一个List<Int>函数实参,也就是这里List<Int>是可以替换List<Any>
}

fun printList(list: List<Any>) {
   
   
//注意:这里函数形参类型是List<Any>,函数内部是不知道外部传入是List<Int>还是List<String>,全部当做List<Any>处理
    list.forEach {
   
   
        println(it)
    }
}

上述操作是合法的,运行结果如下


如果我们上述的函数形参List<Any>换成MutableList<Any>会变成什么样呢?

fun main(args: Array<String>) {
   
   
    
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

熊喵先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值