获取通用列表类,例如:List <number> :: class

时间:2016-05-03 23:33:01

标签: generics kotlin

我有一个通用类型的类Builder<T>,它接受​​一个构造函数参数Class<T>,所以我可以保持类型。这是一个我在java代码中使用很多的类,所以我不想改变签名。 当我尝试使用这样的构造函数时:

Builder<List<Number>>(List<Number>::class)

我收到错误:&#34;只允许在类文字的左侧使用类&#34;

有什么方法可以解决这个问题? 我无法更改Builder的构造函数,太多的java类依赖它。

我理解整个类型的擦除问题,我真的只是想让编译器开心。

4 个答案:

答案 0 :(得分:15)

由于generic type erasure List类对其所有通用实例都有一个实现。您只能获得与List<*>类型相对应的类,因此只能创建Builder<List<*>>

该构建器实例适合构建某些内容的列表。再次由于类型擦除,你可以在未经检查的演员的帮助下自己决定:

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

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

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

并按以下方式使用:

Builder<List<Number>>()

答案 1 :(得分:7)

解决方案是将reified genericssuper class tokens结合使用。

有关解释的方法,请参阅this question。 Kotlin中的构造函数不支持reified泛型,但是你可以使用那里描述的TypeReference编写一个builder工厂函数,它将在运行时保留实际的泛型参数:

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

然后在Builder内,您可以检查type是否为ParameterizedType,如果是,type.actualTypeArguments将包含实际的通用参数。

例如,builder<List<Number>>()将在运行时保留有关Number的信息。

此方法的局限性在于您不能将非实体泛型用作具体类型参数,因为必须在编译时知道该类型。

答案 2 :(得分:0)

如果您已在项目中使用gson库(例如json解析)。为此提供了一个类。 com.google.gson.reflect.TypeToken()。所以你可以使用类似的东西,

 Builder<List<Number>>(object : TypeToken<List<Number>>() {}.type::class)

答案 3 :(得分:-3)

您可能只想使用以下样式,

Array<Number>::class.java

如果您想要类似Class<T>