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

Kotlin泛型子类传入ListRunner时的类型不匹配问题

Kotlin泛型接口列表参数兼容问题解决

我定义了一个带泛型的接口,单类扩展功能运行正常,但无法将该接口子类的列表作为参数传入目标类。

可正常运行的代码如下:

interface Runnable

class FirstRunnable : Runnable
class SecondRunnable : Runnable

interface Runner<in T> where T : Runnable {
    fun run(runnable: T)
}

class FirstRunner : Runner<FirstRunnable> {
    override fun run(runnable: FirstRunnable) = println("first runner")
}

class SecondRunner : Runner<SecondRunnable> {
    override fun run(runnable: SecondRunnable) = println("second runner")
}

问题出在以下代码块:

class ListRunner(private val runners: List<Runner<Runnable>>)

val runner = ListRunner(listOf(FirstRunner(), SecondRunner()))

此时编译器报错:

Type mismatch.
  Required:
    List<Runner<Runnable>>
  Found:
    List<Runner<{FirstRunnable & SecondRunnable}>>

需求是将该列表注入ListRunner,实现一次性运行所有runner,且每个runner内部有规则确保只处理可接受的Runnable实例。


解决方案

结合两位答主的建议,最终解决方案如下:

步骤1:为ListRunner的泛型添加out协变

正如Nishant Jalan指出,需要修改ListRunner的参数类型,添加out关键字实现协变:

class ListRunner(private val runners: List<Runner<out Runnable>>)

步骤2:为Runner接口的方法参数添加@UnsafeVariance注解

正如Sweeper所说:

向其中传入任何内容都是不安全的。Kotlin类型系统会通过提示run方法接受Nothing类型来告知这一点。

因此需要为Runner接口的run方法参数添加@UnsafeVariance注解:

interface Runner<in T> where T : Runnable {
    fun run(runnable: @UnsafeVariance T)
}

注意:@UnsafeVariance仅用于抑制编译器的类型安全报错,本身存在潜在的类型不安全风险。但如果业务中已有前置验证逻辑,能确保Runnable实例被传入正确的runner处理,则可以安全使用此方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 04:18:23