Kotlin中的泛型:为什么需要以及如何使用

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Kotlin 泛型入门



泛型(通用类型)是静态类型编程语言(包括 Kotlin)的关键特性之一。它允许你编写灵活、可复用的代码来处理不同的数据类型,同时在编译时保持严格的类型安全。



假设你需要创建一个存储元素列表的数据结构。没有泛型时,你必须为每种类型编写单独的类(IntList、StringList、UserList)。有了泛型,一个单一的类 MyList<T> 就足够了,它可以适用于任何类型。



// 没有泛型 — 你必须重复代码class IntList(private val items: MutableList<Int>)class StringList(private val items: MutableList<String>)

// 使用泛型 — 一个类适用于所有类型class GenericList<T>(private val items: MutableList<T>) { fun add(item: T) { items.add(item) } fun get(index: Int): T = items[index]}


在本文中,我们将深入探讨 Kotlin 中的泛型工作机制,了解其语法、使用场景以及协变和逆变等高级概念。



泛型基础



声明泛型类和函数



要声明一个泛型类,只需在类名后的尖括号中指定一个或多个类型参数:



class Box<T>(var value: T) {    fun getValue(): T = value    fun setValue(newValue: T) { value = newValue }}

// 使用val intBox = Box<Int>(42)val stringBox = Box<String>("Hello")

// Kotlin 可以推断类型,因此可以简写val anotherBox = Box("自动类型推断")


函数也可以是泛型的。类型参数在函数名前指定:



fun <T> printItem(item: T) {    println("项目: $item")}

fun <T> createPair(first: T, second: T): Pair<T, T> { return Pair(first, second)}

// 使用printItem(123)printItem("文本")val pair = createPair("A", "B")


类型边界



有时你需要限制可用于泛型的类型。这时可以使用关键字 : Type 设置上界:



// 仅限实现了 Comparable 的类型fun <T : Comparable<T>> findMax(a: T, b: T): T {    return if (a > b) a else b}

// 使用 where 设置多个约束fun <T> processItem(item: T) where T : CharSequence, T : Comparable<T> { println("长度: ${item.length}") println("比较结果: ${item.compareTo(item)}")}

// 使用println(findMax(10, 20)) // 20println(findMax("Apple", "Banana")) // "Banana"// findMax(10, "Text") // 编译错误!


型变:in、out 和类型投影



泛型中最复杂但最重要的主题之一是型变。它定义了泛型类型在继承关系中如何相互关联。



不变性(默认)



默认情况下,Kotlin 中的泛型是不变的。这意味着 Box<Number> 和 Box<Int> 互不为子类型,即使 Int 是 Number 的子类型:



val intBox: Box<Int> = Box(42)// val numBox: Box<Number> = intBox // 编译错误!


协变(out)



out 修饰符使类型变为协变。这意味着 Box<Int> 成为 Box<Number> 的子类型。当类型 T 仅用于输出位置(返回值)时使用:



class Producer<out T>(private val item: T) {    fun produce(): T = item  // T 仅在输出位置}                

博客

书籍推荐