为何Kotlin的sumOf函数Lambda内默认不将数字视为Int类型?
Kotlin sumOf重载歧义问题解析
问题重现
执行以下代码时,Kotlin编译器会抛出重载解析歧义错误:
val sum = listOf(1, 2, 3).sumOf { if (it % 2 == 0) 1 else 0 }
错误信息如下:
Kotlin: Overload resolution ambiguity:
public inline funIterable<TypeVariable(T)>.sumOf(selector: (TypeVariable(T)) -> Int): Int defined in kotlin.collections
public inline funIterable<TypeVariable(T)>.sumOf(selector: (TypeVariable(T)) -> Long): Long defined in kotlin.collections
如果显式调用toInt(),错误会消失,但会出现冗余调用警告:
val sum = listOf(1, 2, 3).sumOf { if (it % 2 == 0) 1.toInt() else 0 }
原因分析
Kotlin的数字字面量(如1、0)属于无类型字面量,编译器会根据上下文自动推断其类型。而sumOf函数提供了两个重载:
- 一个接受返回
Int类型的选择器函数,返回Int结果 - 另一个接受返回
Long类型的选择器函数,返回Long结果
由于Kotlin支持Int到Long的隐式拓宽转换,1和0既可以被推断为Int,也可以被推断为Long。此时编译器没有足够的上下文信息确定你要调用哪个重载版本,因此抛出歧义错误。
显式调用1.toInt()时,相当于强制指定了选择器函数的返回类型为Int,编译器就能明确匹配到对应重载。但因为字面量1本身可以直接被当作Int,所以toInt()调用是冗余的,会触发警告。
更优雅的解决方案
不需要使用冗余的toInt(),可以通过以下方式消除歧义:
- 方式1:给目标变量指定类型,让编译器反向推断选择器的返回类型:
val sum: Int = listOf(1, 2, 3).sumOf { if (it % 2 == 0) 1 else 0 }
- 方式2:显式指定lambda的返回类型:
val sum = listOf(1, 2, 3).sumOf { (if (it % 2 == 0) 1 else 0) as Int }
内容的提问来源于stack exchange,提问作者Arpit Shukla
相关产品推荐
相关产品推荐

