为什么这段Kotlin代码报类型不匹配错误:推断类型不符合预期的Any类型
Kotlin类型不匹配报错原因分析
报错信息
Type mismatch: inferred type is {Comparable<*>? & java.io.Serializable?} but Any was expected
出错代码
fun main(){ val nullList = listOf(1, 3, null, "chair", "table", null) val nullArrayList = arrayListOf("this", "house", null, 3, 9) println("This list without the null values is ${nullList.filterNotNull()}") println("This array without the null values is ${nullArrayList.filterNotNull()}") }
报错根因
Kotlin的类型推断机制会自动为集合推导最具体的公共超类型,上述代码中声明的两个集合同时包含了Int、String和null三类元素:
- Int和String的公共非空超类型为
Comparable<*>和java.io.Serializable,二者为平级接口,不存在继承关系 - 结合集合中存在null元素的可空属性,Kotlin会推导出集合的元素类型为两个接口的交叉可空类型:
{Comparable<*>? & java.io.Serializable?}
filterNotNull()方法的返回值会剔除原类型的可空属性,最终得到交叉类型{Comparable<*> & java.io.Serializable}。在Kotlin 1.4及更早版本中,字符串模板仅支持接受明确声明为Any类型的参数,交叉类型无法被自动识别为Any的子类,就会触发该类型不匹配报错。
解决方案
- 方案1:显式声明集合元素类型为
Any?,绕过类型推断得到交叉类型的逻辑:
val nullList = listOf<Any?>(1, 3, null, "chair", "table", null) val nullArrayList = arrayListOf<Any?>("this", "house", null, 3, 9)
- 方案2:将过滤后的结果调用
toString()显式转为字符串后再插入字符串模板:
println("This list without the null values is ${nullList.filterNotNull().toString()}")
- 方案3:升级Kotlin版本到1.5及以上,高版本已经优化了交叉类型的自动转型逻辑,该场景不会再触发报错。
内容的提问来源于stack exchange,提问作者Jeo Stinab
相关产品推荐
相关产品推荐

