kotlin 使用泛型获取列表的类,例如:List< Number>::class

qco9c6ql  于 2023-03-30  发布在  Kotlin
关注(0)|答案(2)|浏览(184)

我有一个泛型类型的类Builder<T>,它接受一个构造函数参数Class<T>,这样我就可以保留类型。这是一个我在java代码中经常使用的类,所以我不想改变签名。当我尝试像这样使用构造函数时:
Builder<List<Number>>(List<Number>::class)
我得到一个错误:“只允许类位于类文本的左手”
有什么办法解决这个问题吗?我不能改变Builder的构造函数,太多的java类依赖于它。
我理解整个类型擦除问题,我真的只是想让编译器高兴。

l2osamch

l2osamch1#

由于generic type erasureList类的所有泛型示例化都只有一个实现。您只能获得与List<*>类型对应的类,因此只能创建Builder<List<*>>
该构建器示例适合于构建一个 something 的列表。同样,由于类型擦除,您可以在未检查的强制转换的帮助下自行决定该something是什么:

Builder(List::class.java) as Builder<List<Number>>
Builder(List::class.java as Class<List<Number>>)

另一种方法是创建内联具体化的helper函数:

inline fun <reified T : Any> Builder() = Builder(T::class.java)

并按以下方式使用:

Builder<List<Number>>()
46scxncf

46scxncf2#

解决方案是结合使用具体化泛型和super class tokens
Kotlin中的构造函数不支持具体化的泛型,但你可以使用这里描述的TypeReference来编写一个builder工厂函数,它将在运行时保留实际的泛型参数:

inline fun <reified T: Any> builder(): Builder<T> {
    val type = object : TypeReference<T>() {}.type
    return Builder(type)
}

然后在Builder中,您可以检查type是否是ParameterizedType,如果是,则type.actualTypeArguments将包含实际的泛型参数。
例如,builder<List<Number>>()将在运行时保留有关Number的信息。
这种方法的局限性在于不能将非具体化泛型用作具体化类型参数,因为该类型必须在编译时已知。

相关问题