PAYATHON 2026

Kotlin 调用泛型函数时,如何只指定返回类型?

数据小许

可以使用 _ 类型实参占位符。按照原函数的类型参数顺序,将调用写成 callPy2<_, _, Int>(...),只需指定返回类型 Tout,两个输入类型仍由编译器推断。Kotlin 从 1.7.0 开始支持该语法。Kotlin 1.7.0 官方说明

使用 _ 指定需要推断的位置

原函数的类型参数依次是:

<Tin0, Tin1, Tout>

因此,前两个位置填 _,第三个位置填写返回类型:

val result = callPy2<_, _, Int>("multi", 3, 4)

val total: Int = 1000 + callPy2<_, _, Int>("multi", 3, 4)

两个输入参数都是 Int,编译器会据此推断 Tin0 和 Tin1;第三个类型实参将 Tout 指定为 Int。

原来的 Float 示例也可以写成:

val resultC = 10000 + callPy2<_, _, Float>("test", 3, 4f)
assertEquals(10123f, resultC)

这里的 Tin0 推断为 Int,Tin1 推断为 Float,返回类型为 Float。_ 让编译器推断对应位置的类型,并不代表 Any 或任意类型。Kotlin 泛型文档

为什么单独赋值可以,放进加法表达式却会报错?

下面的声明直接为函数调用提供了期望类型:

val result: Int = callPy2("multi", 3, 4)

函数调用需要返回 Int,编译器因此能够确定 Tout。

下面的声明则用 Int 约束整个加法表达式的结果:

val result: Int = 1000 + callPy2("multi", 3, 4)

加法需要进行运算符重载解析,外层结果类型不能直接等同于右侧函数调用的返回类型。遇到这种推断失败时,可以在函数调用处指定 Tout,无须依赖外层表达式传递类型信息。

不使用 _ 时,可以先声明带类型的局部变量

如果项目使用的 Kotlin 语言版本不支持该语法,或者希望保留完全省略类型实参的调用形式,可以拆成两步:

val pyResult: Int = callPy2("multi", 3, 4)
val result = 1000 + pyResult

这样仍不需要填写 Tin0 和 Tin1,也能清楚地表达 Python 调用结果应按什么类型解码。

为什么不能写成 callPy2<Int> 或 callPy2<Tout=Int>?

原函数有三个类型参数,callPy2<Int>(...) 不能表示只指定最后一个。显式类型实参按声明顺序匹配,其余位置需要填写类型或 _ 占位符。

Kotlin 也不支持 callPy2<Tout=Int>(...) 这种命名类型实参语法。命名值参数的规则不能直接用于类型实参。

以上代码使用已给出定义的 callPy2。如果 call、callPy.call 等函数的签名不同,需要按各自的类型参数顺序填写。

显式指定 Tout 解决的是编译阶段的类型推断问题。实际 JSON 数据仍须能够被解码为该类型;编译通过并不保证进程返回的数据一定符合预期。

备注:内容仅供参考。