Kotlin中KFunction2为何无法作为可显式声明的参数类型
Kotlin函数引用参数类型问题解答
首先修正示例代码的语法错误:你定义的Cursor接口使用了小括号包裹成员,不符合Kotlin语法,正确写法如下:
interface Cursor { fun seekOrNext(target: String): Boolean fun seekOrPrevious(target: String): Boolean }
关于KFunction2无法声明的结论
你的推测完全正确:
- 后缀带数字的
KFunction0到KFunction22均为Kotlin编译器内部使用的合成类型,不属于公开可引用的API,在kotlin-stdlib、kotlin-reflect依赖中没有对应的实体类定义,属于不可指称类型,开发者无法在源码中显式声明该类型的参数或变量,即使引入反射依赖也会报类型不存在的编译错误。 - IDE类型提示中显示
KFunction2,只是IDE读取了编译器内部的类型推断中间结果,不代表该类型可以在业务代码中直接使用。
参数位置的正确实现
你需要的类型需要同时满足两个能力:支持move(cursor, target)的双参数调用语法、可访问.name属性获取函数名。在Kotlin 1.6.21版本中,兼容性最好的实现方式是通过函数类型声明参数,在函数内部增加类型校验,避免传入普通lambda:
import kotlin.reflect.KFunction fun moveCursorAndLog( cursor: Cursor, move: (Cursor, String) -> Boolean, target: String ): Boolean { check(move is KFunction<*>) { "Only Cursor interface method references are allowed" } println("Moving cursor with ${move.name} to '${target}'.") return move(cursor, target) }
效果说明
- 传入
Cursor::seekOrNext、Cursor::seekOrPrevious这类方法引用时,代码可正常编译运行,能正确打印方法名、执行游标移动逻辑。 - 传入普通lambda表达式时,会在运行时触发校验异常,拦截不符合预期的参数。
- 类型校验逻辑无额外反射开销:方法引用在运行时本身就是
KFunction接口的实现类,is判断仅为普通的类型检查,不会触发高成本的反射解析。
注:Kotlin 1.6.21暂不支持在参数声明位置直接通过
&操作符定义交叉类型(例如(Cursor, String) -> Boolean & KFunction<Boolean>),因此无法在编译期完全限制仅传入方法引用,上述运行时校验是当前版本最稳妥的方案。
内容的提问来源于stack exchange,提问作者Martin Häusler
相关产品推荐
相关产品推荐

