首页 文章

获取具有通用的列表类,例如:List <Number> :: class

提问于
浏览
11

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

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

我收到一个错误:“只允许类在类文字的左侧”

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

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

2 回答

  • 6

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

    该构建器实例适用于构建某个列表 . 再次由于类型擦除,您可以在未经检查的强制转换的帮助下自行决定:

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

    另一种方法是创建内联reified帮助函数:

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

    并按以下方式使用它:

    Builder<List<Number>>()
    
  • 14

    解决方案是使用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 的信息 .

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

相关问题