💡 导读:泛型是Kotlin类型系统的重要组成部分,它让我们能够编写类型安全的代码,同时保持代码的灵活性和复用性。本文将带你深入探索Kotlin泛型的世界!

📋 目录


📚 泛型基础

基本概念

// 泛型类
class Box<T>(var content: T) {
    fun get(): T = content
    fun set(value: T) {
        content = value
    }
}

// 泛型函数
fun <T> printItem(item: T) {
    println("Item: $item")
}

// 使用泛型
fun main() {
    val stringBox = Box("Hello")
    val intBox = Box(42)
    
    println(stringBox.get())  // Hello
    println(intBox.get())     // 42
    
    printItem("Kotlin")       // Item: Kotlin
    printItem(100)            // Item: 100
}

集合中的泛型

fun main() {
    // 泛型集合
    val stringList: List<String> = listOf("a", "b", "c")
    val intList: List<Int> = listOf(1, 2, 3)
    
    // 泛型Map
    val stringMap: Map<String, Int> = mapOf("a" to 1, "b" to 2)
    
    // 类型推断
    val inferredList = listOf("x", "y", "z")  // 自动推断为List<String>
    val inferredMap = mapOf("x" to 1, "y" to 2)  // 自动推断为Map<String, Int>
    
    println(stringList)
    println(intList)
    println(stringMap)
}

🎯 类型参数

多个类型参数

// 多个类型参数
class Pair<T, U>(val first: T, val second: U) {
    fun swap(): Pair<U, T> = Pair(second, first)
    
    override fun toString(): String = "($first, $second)"
}

// 使用多个类型参数
fun main() {
    val pair = Pair("Hello", 42)
    println(pair)  // (Hello, 42)
    
    val swapped = pair.swap()
    println(swapped)  // (42, Hello)
    
    // 不同类型参数
    val mixedPair = Pair("String", true)
    println(mixedPair)  // (String, true)
}

泛型函数

// 泛型函数
fun <T> createList(vararg items: T): List<T> {
    return items.toList()
}

fun <T> findFirst(list: List<T>, predicate: (T) -> Boolean): T? {
    for (item in list) {
        if (predicate(item)) {
            return item
        }
    }
    return null
}

// 使用泛型函数
fun main() {
    val stringList = createList("a", "b", "c")
    val intList = createList(1, 2, 3, 4, 5)
    
    println(stringList)  // [a, b, c]
    println(intList)     // [1, 2, 3, 4, 5]
    
    val firstEven = findFirst(intList) { it % 2 == 0 }
    println("第一个偶数: $firstEven")  // 第一个偶数: 2
}

🔒 泛型约束

上界约束

// 上界约束 - T必须是Number的子类型
fun <T : Number> sum(list: List<T>): Double {
    return list.sumOf { it.toDouble() }
}

// 多个上界约束
fun <T> callToString(value: T) where T : CharSequence, T : Comparable<T> {
    println("Length: ${value.length}")
    println("Value: $value")
}

// 使用约束
fun main() {
    val intList = listOf(1, 2, 3, 4, 5)
    val doubleList = listOf(1.5, 2.5, 3.5)
    
    println("整数和: ${sum(intList)}")      // 整数和: 15.0
    println("浮点数和: ${sum(doubleList)}")  // 浮点数和: 7.5
    
    callToString("Hello")  // 可以调用,String实现了CharSequence和Comparable
    // callToString(42)    // 编译错误,Int不满足约束
}

类型约束

// 类型约束
interface Printable {
    fun print()
}

class Document : Printable {
    override fun print() = println("打印文档")
}

class Image : Printable {
    override fun print() = println("打印图片")
}

// 泛型函数使用类型约束
fun <T : Printable> printItem(item: T) {
    item.print()
}

// 使用
fun main() {
    val document = Document()
    val image = Image()
    
    printItem(document)  // 打印文档
    printItem(image)     // 打印图片
}

🔄 型变

协变(Covariant)

// 协变 - 使用out关键字
class Producer<out T>(private val value: T) {
    fun get(): T = value
    // fun set(value: T) { }  // 编译错误,协变类型不能作为参数
}

// 协变的使用
fun main() {
    val stringProducer: Producer<String> = Producer("Hello")
    val anyProducer: Producer<Any> = stringProducer  // 协变,可以赋值
    
    println(anyProducer.get())  // Hello
}

// 协变集合
fun main() {
    val stringList: List<String> = listOf("a", "b", "c")
    val anyList: List<Any> = stringList  // List是协变的
    
    println(anyList)  // [a, b, c]
}

逆变(Contravariant)

// 逆变 - 使用in关键字
class Consumer<in T> {
    fun consume(value: T) {
        println("消费: $value")
    }
    // fun get(): T { }  // 编译错误,逆变类型不能作为返回值
}

// 逆变的使用
fun main() {
    val anyConsumer: Consumer<Any> = Consumer()
    val stringConsumer: Consumer<String> = anyConsumer  // 逆变,可以赋值
    
    stringConsumer.consume("Hello")  // 消费: Hello
}

// 逆变函数类型
fun main() {
    val anyHandler: (Any) -> Unit = { println("处理: $it") }
    val stringHandler: (String) -> Unit = anyHandler  // 逆变
    
    stringHandler("Hello")  // 处理: Hello
}

不变(Invariant)

// 不变 - 默认情况
class MutableBox<T>(var content: T) {
    fun get(): T = content
    fun set(value: T) {
        content = value
    }
}

// 不变的使用
fun main() {
    val stringBox: MutableBox<String> = MutableBox("Hello")
    // val anyBox: MutableBox<Any> = stringBox  // 编译错误,不变类型不能赋值
    
    println(stringBox.get())  // Hello
}

⭐ 星投影

星投影基础

// 星投影 - 不知道具体类型时使用
fun printList(list: List<*>) {
    for (item in list) {
        println(item)
    }
}

// 星投影的使用
fun main() {
    val stringList = listOf("a", "b", "c")
    val intList = listOf(1, 2, 3)
    
    printList(stringList)  // a, b, c
    printList(intList)     // 1, 2, 3
}

// 星投影的限制
fun main() {
    val list: List<*> = listOf("a", "b", "c")
    
    // 可以读取
    println(list[0])  // a
    
    // 不能写入(类型不安全)
    // list[0] = "x"  // 编译错误
}

星投影的高级用法

// 星投影与泛型函数
fun <T> createList(size: Int, defaultValue: T): List<T> {
    return List(size) { defaultValue }
}

fun main() {
    val stringList = createList(3, "default")
    val intList = createList(3, 0)
    
    println(stringList)  // [default, default, default]
    println(intList)     // [0, 0, 0]
    
    // 使用星投影
    val anyList: List<*> = stringList
    println(anyList)     // [default, default, default]
}

🎯 实战应用

1. 泛型缓存

class Cache<T> {
    private val storage = mutableMapOf<String, T>()
    
    fun put(key: String, value: T) {
        storage[key] = value
    }
    
    fun get(key: String): T? {
        return storage[key]
    }
    
    fun remove(key: String) {
        storage.remove(key)
    }
    
    fun clear() {
        storage.clear()
    }
    
    fun size(): Int = storage.size
}

// 使用泛型缓存
fun main() {
    val stringCache = Cache<String>()
    val intCache = Cache<Int>()
    
    stringCache.put("name", "张三")
    stringCache.put("city", "北京")
    
    intCache.put("age", 25)
    intCache.put("score", 95)
    
    println("姓名: ${stringCache.get("name")}")
    println("年龄: ${intCache.get("age")}")
    println("缓存大小: ${stringCache.size()}")
}

2. 泛型比较器

class GenericComparator<T>(private val compareFunction: (T, T) -> Int) {
    fun compare(a: T, b: T): Int = compareFunction(a, b)
    
    fun isGreater(a: T, b: T): Boolean = compare(a, b) > 0
    fun isLess(a: T, b: T): Boolean = compare(a, b) < 0
    fun isEqual(a: T, b: T): Boolean = compare(a, b) == 0
}

// 使用泛型比较器
fun main() {
    val stringComparator = GenericComparator<String> { a, b -> a.compareTo(b) }
    val intComparator = GenericComparator<Int> { a, b -> a.compareTo(b) }
    
    println("字符串比较: ${stringComparator.isGreater("b", "a")}")  // true
    println("整数比较: ${intComparator.isLess(5, 10)}")            // true
    println("相等比较: ${intComparator.isEqual(5, 5)}")            // true
}

3. 泛型工厂

interface Factory<T> {
    fun create(): T
}

class StringFactory : Factory<String> {
    override fun create(): String = "默认字符串"
}

class IntFactory : Factory<Int> {
    override fun create(): Int = 42
}

class ListFactory<T> : Factory<List<T>> {
    override fun create(): List<T> = emptyList()
}

// 使用泛型工厂
fun main() {
    val stringFactory = StringFactory()
    val intFactory = IntFactory()
    val listFactory = ListFactory<String>()
    
    println("字符串: ${stringFactory.create()}")
    println("整数: ${intFactory.create()}")
    println("列表: ${listFactory.create()}")
}

4. 泛型工具类

object GenericUtils {
    // 泛型交换函数
    fun <T> swap(array: Array<T>, i: Int, j: Int) {
        val temp = array[i]
        array[i] = array[j]
        array[j] = temp
    }
    
    // 泛型查找函数
    fun <T> find(array: Array<T>, predicate: (T) -> Boolean): T? {
        for (item in array) {
            if (predicate(item)) {
                return item
            }
        }
        return null
    }
    
    // 泛型复制函数
    fun <T> copy(source: Array<T>, destination: Array<T>) {
        val minSize = minOf(source.size, destination.size)
        for (i in 0 until minSize) {
            destination[i] = source[i]
        }
    }
}

// 使用泛型工具类
fun main() {
    val stringArray = arrayOf("a", "b", "c", "d")
    val intArray = arrayOf(1, 2, 3, 4, 5)
    
    // 交换元素
    GenericUtils.swap(stringArray, 0, 2)
    println("交换后: ${stringArray.contentToString()}")  // [c, b, a, d]
    
    // 查找元素
    val found = GenericUtils.find(intArray) { it > 3 }
    println("找到大于3的数: $found")  // 4
    
    // 复制数组
    val destArray = Array(3) { "" }
    GenericUtils.copy(stringArray, destArray)
    println("复制后: ${destArray.contentToString()}")  // [c, b, a]
}

📊 最佳实践

1. 类型安全

// 使用泛型确保类型安全
class SafeContainer<T> {
    private var value: T? = null
    
    fun set(value: T) {
        this.value = value
    }
    
    fun get(): T? = value
    
    fun isSet(): Boolean = value != null
}

// 使用约束确保功能
fun <T : Comparable<T>> max(a: T, b: T): T {
    return if (a > b) a else b
}

2. 性能优化

// 使用内联泛型函数
inline fun <reified T> createInstance(): T {
    return T::class.java.getDeclaredConstructor().newInstance()
}

// 使用泛型避免装箱
fun <T> processList(list: List<T>) {
    // 避免装箱/拆箱开销
    for (item in list) {
        // 处理item
    }
}

3. 代码复用

// 泛型接口
interface Repository<T> {
    fun save(item: T)
    fun findById(id: String): T?
    fun findAll(): List<T>
    fun delete(id: String)
}

// 具体实现
class UserRepository : Repository<User> {
    private val users = mutableMapOf<String, User>()
    
    override fun save(item: User) {
        users[item.id] = item
    }
    
    override fun findById(id: String): User? = users[id]
    
    override fun findAll(): List<User> = users.values.toList()
    
    override fun delete(id: String) {
        users.remove(id)
    }
}

data class User(val id: String, val name: String)

🎯 总结与进阶

今日收获

通过本篇文章,你已经掌握了:

  1. 泛型基础 - 泛型类、泛型函数的概念
  2. 类型参数 - 多个类型参数的使用
  3. 泛型约束 - 上界约束、类型约束
  4. 型变 - 协变、逆变、不变
  5. 星投影 - 未知类型参数的处理
  6. 实战应用 - 泛型缓存、比较器、工厂等

🚀 进阶学习方向

  1. 反射与泛型 - 运行时类型信息
  2. 泛型与协程 - 异步泛型编程
  3. 泛型DSL - 类型安全的DSL构建
  4. 高级型变 - 复杂的型变场景

💡 最佳实践

  1. 优先使用泛型 - 提高代码复用性
  2. 合理使用约束 - 确保类型安全
  3. 理解型变 - 正确使用协变和逆变
  4. 避免类型擦除 - 注意运行时类型信息

📚 推荐资源


🌟 下期预告:我们将探索Kotlin的反射世界,学习运行时类型信息,掌握动态编程的能力。敬请期待!


📝 作者寄语:泛型是类型安全的基石,它让我们能够编写既灵活又安全的代码。让我们一起在泛型的世界里探索更多可能!

🔗 相关文章


如果这篇文章对你有帮助,请点赞、收藏、关注,你的支持是我创作的动力! 🚀

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐