Kotlin:为List<Any>添加泛型时的类型不匹配问题
解决泛型列表拼接的类型不匹配问题
先看你的代码场景:
你定义了一个泛型数据类:
data class MyObject<T>( val entity: T )
尝试拼接两个不同泛型参数的MyObject列表:
fun concatLists(): List<MyObject<Any>> { val listOfAs = listOf(MyObject<A>()) val listOfBs = listOf(MyObject<B>()) return mutableListOf<MyObject<Any>>().also { it.addAll(listOfAs) it.addAll(listOfBs) } }
但遇到了类型不匹配错误:
Type mismatch. Required: Collection<MyObject<Any>> Found: List<MyObject<A>>
错误原因
你混淆了泛型的不变性和普通类的继承关系。Kotlin中泛型默认是不变的:哪怕A是Any的子类,MyObject<A>也不是MyObject<Any>的子类,两者之间没有继承关系。虽然List是Collection的子类,但泛型参数的不兼容性导致整个集合类型不匹配。
解决方案
有两种常用的解决方式:
1. 让MyObject支持协变
因为你的MyObject只有只读的val entity,属于生产型泛型(只向外暴露T类型的值,不接收T类型的输入),可以给泛型参数加上out关键字开启协变:
data class MyObject<out T>( val entity: T )
开启协变后,MyObject<A>会被视为MyObject<Any>的子类型,此时你的原代码就能正常编译运行——因为List<MyObject<A>>可以适配Collection<MyObject<Any>>的要求。
2. 不修改MyObject,强制类型转换
如果无法修改MyObject的定义,可以通过类型转换让列表适配目标类型:
fun concatLists(): List<MyObject<Any>> { val listOfAs = listOf(MyObject<A>()) val listOfBs = listOf(MyObject<B>()) return mutableListOf<MyObject<Any>>().also { it.addAll(listOfAs as List<MyObject<Any>>) it.addAll(listOfBs as List<MyObject<Any>>) } }
或者更简洁的写法:
fun concatLists(): List<MyObject<Any>> { val listOfAs = listOf(MyObject<A>()) val listOfBs = listOf(MyObject<B>()) return (listOfAs + listOfBs) as List<MyObject<Any>> }
注意:这种方式需要确保类型安全,因为如果MyObject后续添加了可写的T类型属性,强制转换可能导致运行时错误,但在当前只读的场景下是安全的。
内容的提问来源于stack exchange,提问作者Henry Williams
相关产品推荐
相关产品推荐

