我有一个泛型类型的类Builder<T>,它接受一个构造函数参数Class<T>,这样我就可以保留类型。这是一个我在java代码中经常使用的类,所以我不想改变签名。当我尝试像这样使用构造函数时:Builder<List<Number>>(List<Number>::class)我得到一个错误:“只允许类位于类文本的左手”有什么办法解决这个问题吗?我不能改变Builder的构造函数,太多的java类依赖于它。我理解整个类型擦除问题,我真的只是想让编译器高兴。
Builder<T>
Class<T>
Builder<List<Number>>(List<Number>::class)
Builder
l2osamch1#
由于generic type erasure,List类的所有泛型示例化都只有一个实现。您只能获得与List<*>类型对应的类,因此只能创建Builder<List<*>>。该构建器示例适合于构建一个 something 的列表。同样,由于类型擦除,您可以在未检查的强制转换的帮助下自行决定该something是什么:
List
List<*>
Builder<List<*>>
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>>()
46scxncf2#
解决方案是结合使用具体化泛型和super class tokens。Kotlin中的构造函数不支持具体化的泛型,但你可以使用这里描述的TypeReference来编写一个builder工厂函数,它将在运行时保留实际的泛型参数:
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的信息。这种方法的局限性在于不能将非具体化泛型用作具体化类型参数,因为该类型必须在编译时已知。
type
ParameterizedType
type.actualTypeArguments
builder<List<Number>>()
Number
2条答案
按热度按时间l2osamch1#
由于generic type erasure,
List
类的所有泛型示例化都只有一个实现。您只能获得与List<*>
类型对应的类,因此只能创建Builder<List<*>>
。该构建器示例适合于构建一个 something 的列表。同样,由于类型擦除,您可以在未检查的强制转换的帮助下自行决定该something是什么:
另一种方法是创建内联具体化的helper函数:
并按以下方式使用:
46scxncf2#
解决方案是结合使用具体化泛型和super class tokens。
Kotlin中的构造函数不支持具体化的泛型,但你可以使用这里描述的
TypeReference
来编写一个builder
工厂函数,它将在运行时保留实际的泛型参数:然后在
Builder
中,您可以检查type
是否是ParameterizedType
,如果是,则type.actualTypeArguments
将包含实际的泛型参数。例如,
builder<List<Number>>()
将在运行时保留有关Number
的信息。这种方法的局限性在于不能将非具体化泛型用作具体化类型参数,因为该类型必须在编译时已知。