Kotlin泛型详解:类型安全的艺术
泛型基础- 泛型类、泛型函数的概念类型参数- 多个类型参数的使用泛型约束- 上界约束、类型约束型变- 协变、逆变、不变星投影- 未知类型参数的处理实战应用- 泛型缓存、比较器、工厂等。
·
💡 导读:泛型是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)
🎯 总结与进阶
今日收获
通过本篇文章,你已经掌握了:
- 泛型基础 - 泛型类、泛型函数的概念
- 类型参数 - 多个类型参数的使用
- 泛型约束 - 上界约束、类型约束
- 型变 - 协变、逆变、不变
- 星投影 - 未知类型参数的处理
- 实战应用 - 泛型缓存、比较器、工厂等
🚀 进阶学习方向
- 反射与泛型 - 运行时类型信息
- 泛型与协程 - 异步泛型编程
- 泛型DSL - 类型安全的DSL构建
- 高级型变 - 复杂的型变场景
💡 最佳实践
- 优先使用泛型 - 提高代码复用性
- 合理使用约束 - 确保类型安全
- 理解型变 - 正确使用协变和逆变
- 避免类型擦除 - 注意运行时类型信息
📚 推荐资源
🌟 下期预告:我们将探索Kotlin的反射世界,学习运行时类型信息,掌握动态编程的能力。敬请期待!
📝 作者寄语:泛型是类型安全的基石,它让我们能够编写既灵活又安全的代码。让我们一起在泛型的世界里探索更多可能!
🔗 相关文章:
如果这篇文章对你有帮助,请点赞、收藏、关注,你的支持是我创作的动力! 🚀
更多推荐
所有评论(0)