栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Kotlin泛型 总结

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Kotlin泛型 总结

泛型:参数化类型,可以接收多种不同的类型,来达到代码的通用性。kotlin泛型和Java类似。
优点:

  1. 类型检查,能在编译时检查错误
  2. 语义化,直观看到存在什么类型的数据
  3. 自动类型转换
  4. 代码的通用性
class Box(t: T) {
    var value = t
}
1.Java为什么不能声明一个泛型数组
Apple[] appleArr =new Apple[10]
Fruit[] fruitArray = appleArr
fruitArray[0] = new Banana();//编译通过,运行ArrayStoreException

List appleList = new ArrayList();
List fruitList = appleList;// 不允许

appleArr可以赋值给fruitArray,但是appleList不能赋值给fruitList。
数组是协变的,list 是不变的。Object[] 是所有对象数组的父亲,而List 却不是List的父亲

但是kotlin的数组是支持泛型的,所以也不再协变

型变

声明处型变(declaration-site variance)与类型投影(type projections)

1.声明处型变out in

在 Kotlin 中,有一种方法向编译器解释这种情况。这称为声明处型变:我们可以标注 Source 的类型参数 T 来确保它仅从 Source 成员中返回(生产),并从不被消费。

interface Source {
    fun nextT(): T
}

fun demo(strs: Source) {
    val objects: Source = strs // 这个没问题,因为 T 是一个 out-参数
    // ……
}
//简而言之,他们说类 C 是在参数 T 上是协变的,或者说 T 是一个协变的类型参数。 你可以认为 C 是 T 的生产者,而不是 T 的消费者

out修饰符称为型变注解,并且由于它在类型参数声明处提供,所以我们称之为声明处型变。 这与 Java 的使用处型变相反,其类型用途通配符使得类型协变。

除了 out,Kotlin 又补充了一个型变注释:in。它使得一个类型参数逆变:只可以被消费而不可以被生产。逆变类型的一个很好的例子是 Comparable:

interface Comparable {
    operator fun compareTo(other: T): Int
}

fun demo(x: Comparable) {
    x.compareTo(1.0) // 1.0 拥有类型 Double,它是 Number 的子类型
    // 因此,我们可以将 x 赋给类型为 Comparable  的变量
    val y: Comparable = x // OK!
}
2.类型投影
fun copy(from: Array, to: Array) { …… }

这里out 称为类型投影:我们说from不仅仅是一个数组,而是一个受限制的(投影的)数组:我们只可以调用返回类型为类型参数 T 的方法,如上,这意味着我们只能调用 get()。这就是我们的使用处型变的用法,并且是对应于 Java 的 Array、 但使用更简单些的方式。

也可以使用 in 投影一个类型:

fun fill(dest: Array, value: String) { …… }

Array 对应于 Java 的 Array,也就是说,你可以传递一个 CharSequence 数组或一个 Object 数组给 fill() 函数。

3.星投影 ????

Kotlin 为此提供了所谓的星投影语法:

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

如果泛型类型具有多个类型参数,则每个类型参数都可以单独投影。 例如,如果类型被声明为 interface Function ,我们可以想象以下星投影:

  • Function<*, String> 表示 Function
  • Function 表示 Function
  • Function<*, *> 表示 Function

注意:星投影非常像 Java 的原始类型,但是安全。

4、泛型约束

上界

最常见的约束类型是与 Java 的 extends 关键字对应的 上界:

fun > sort(list: List) {  …… }

冒号之后指定的类型是上界:只有 Comparable 的子类型可以替代 T。 例如:

sort(listOf(1, 2, 3)) // OK。Int 是 Comparable 的子类型
sort(listOf(HashMap())) // 错误:HashMap 不是 Comparable> 的子类型

默认的上界(如果没有声明)是 Any?。在尖括号中只能指定一个上界。 如果同一类型参数需要多个上界,我们需要一个单独的 where-子句:

fun  copyWhenGreater(list: List, threshold: T): List
    where T : CharSequence,
          T : Comparable {
    return list.filter { it > threshold }.map { it.toString() }
}

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

5.类型擦除

Kotlin 为泛型声明用法执行的类型安全检测仅在编译期进行。 运行时泛型类型的实例不保留关于其类型实参的任何信息。 其类型信息称为被擦除

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/855091.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号