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

Kotlin如何让函数接受任意派生类的KClass参数?

如何让Kotlin函数接受任意派生类的KClass类型参数?

问题重现

你编写的代码尝试让函数接收任意T派生类的KClass数组,但编译器抛出类型不匹配错误:

原代码:

import kotlin.reflect.KClass

fun <T: Any> test(arr: Array<KClass<T>>) {
    print(arr)
}

fun main() {
    test<Number>(arrayOf(Int::class, Short::class))
}

错误信息:

Type mismatch: inferred type is Number but Int was expected
Type mismatch: inferred type is Short but Int was expected
Type mismatch: inferred type is Number but Short was expected
Type mismatch: inferred type is Int but Short was expected
Type mismatch: inferred type is KClass<Short> but KClass<Int> was expected
Type mismatch: inferred type is KClass<Int> but KClass<Short> was expected
Type mismatch: inferred type is KClass<Short> but KClass<Int> was expected

问题原因

核心问题在于容器类型的协变性:

  1. KClass本身是协变的(定义为KClass<out T : Any>),这意味着KClass<Int>可以视为KClass<out Number>的子类型;
  2. 但Array是不变类型,Array<KClass<Number>>只能接收KClass<Number>类型的元素,无法直接容纳KClass<Int>或KClass<Short>这类子类型实例。

解决方案

有两种常用的修改方式:

方案1:给数组和KClass添加协变投影

修改函数参数为Array<out KClass<out T>>,通过out投影允许容器接收协变类型:

import kotlin.reflect.KClass

fun <T: Any> test(arr: Array<out KClass<out T>>) {
    print(arr)
}

fun main() {
    test<Number>(arrayOf(Int::class, Short::class))
}
  • 第一个out表示我们只读取数组元素(不修改数组),允许数组本身协变;
  • 第二个out表示允许传入T子类的KClass实例。

方案2:改用List代替Array

Kotlin中的List默认是协变的(List<out E>),直接替换数组为List即可:

import kotlin.reflect.KClass

fun <T: Any> test(arr: List<KClass<out T>>) {
    print(arr)
}

fun main() {
    test<Number>(listOf(Int::class, Short::class))
}

这种方式更符合Kotlin的惯用写法,List的协变特性天然适配这种场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 16:50:26