You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin中如何为lambda类型添加编译时检查?

为Kotlin集合扩展函数实现更严格的泛型类型检查

问题描述

想要实现类似filter、map的集合扩展函数filterIn,但当前泛型约束过于宽松,导致一些不符合类型要求的调用能通过编译,本应在编译阶段就报错。

现有两个filterIn扩展函数:

inline fun <T> Iterable<T>.filterIn(other: Collection<T>): List<T> {
    return this.filter { it in other }
}

inline fun <T, R> Iterable<T>.filterIn(other: Collection<R>, transform: (T) -> (R)): List<T> {
    return this.filter { transform(it) in other }
}

以下调用本应编译失败,但实际能正常通过:

// 集合元素类型不匹配,本应编译失败
listOf("1", "2", "3").filterIn(setOf(1, 2)) == emptyList<String>() 

// Lambda返回类型与集合元素类型不匹配,本应编译失败
listOf("1", "2", "3").filterIn(setOf(1, 2)) { it } == emptyList<String>() 

// Lambda返回类型与集合元素类型不匹配,本应编译失败
listOf("1", "2", "3").filterIn(setOf(1, 2)) { mapOf("foo" to "bar") } == emptyList<String>() 

问题根源

Kotlin编译器会自动推导泛型类型为能让代码合法的最宽泛父类(比如Any),即使实际类型不匹配。例如第一个错误调用中,编译器会将T推导为Any,因为String和Int的共同父类是Any,从而让代码通过编译。

解决方案

通过泛型类型相等约束(Kotlin 1.3+支持),强制要求相关类型必须完全匹配,阻止编译器自动向上推导到公共父类。

修改后的扩展函数

// 无transform参数版本:强制集合元素类型与调用者元素类型完全一致
inline fun <reified T, reified U> Iterable<T>.filterIn(other: Collection<U>): List<T> where T == U {
    return this.filter { it in other }
}

// 带transform参数版本:强制transform返回类型与集合元素类型完全一致
inline fun <T, reified R, reified U> Iterable<T>.filterIn(other: Collection<U>, transform: (T) -> R): List<T> where R == U {
    return this.filter { transform(it) in other }
}

效果验证

  • 类型不匹配的调用会直接在编译期报错,比如listOf("1").filterIn(setOf(1))会因为T=String与U=Int不满足T==U而编译失败。
  • 合法调用正常通过,比如listOf(1,2).filterIn(setOf("1","2")) { it.toString() }中,R=String与U=String匹配,可正常编译运行。

内容的提问来源于stack exchange,提问作者Claudio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 05:40:35