在kotlin中创建泛型类的新实例的正确方法是什么?

paw*_*gio 17 generics class kotlin

我使用以下初始化:

val entityClass = javaClass<Class<T>>()
var entity = entityClass.newInstance().newInstance()
Run Code Online (Sandbox Code Playgroud)

但它是错的,并导致IllegalAccessExceptionjava.lang.Class.newInstance(Class.java:1208)

Kir*_*man 29

如果让IntelliJ添加显式类型信息,您会看到它entityClass实际上是类型Class<Class<String>>.我不确定这是不是你想要的.在第2行中,您首先要创建一个实例Class<T>然后创建一个实例,T但这无论如何都是不可能的,因为有关通用信息T在运行时会丢失.除此之外,您无法直接实例化类对象.

一种可能的解决方案是向Class<T>函数或类添加类型参数,并使用它来实例化这样的对象.

fun <T> foo(entityClass: Class<T>) {
    var entity: T = entityClass.newInstance()
}

fun test() {
    foo(Object::class.java)
}
Run Code Online (Sandbox Code Playgroud)

但实际上,如果不使用反射,那就是更优雅的解决方案.定义方法类型的参数() -> T并使用构造函数引用.这是我关于构造函数引用的相关问题,这里是代码:

fun <T> foo2(factory: () -> T) {
    var entity: T = factory()
}

fun test() {
    foo2(::Object)
}
Run Code Online (Sandbox Code Playgroud)


Coo*_*ind 6

感谢Kirill Rakhman,我写了一个类似的答案(针对 Android 适配器)。这里的区别在于类的参数。

private fun <T> createItem(
    viewGroup: ViewGroup,
    layoutRes: Int,
    method: (View) -> T
): T {
    val view = LayoutInflater.from(viewGroup.context).inflate(layoutRes, viewGroup, false)
    return method(view) // Creates T(view).
}
Run Code Online (Sandbox Code Playgroud)

然后这样使用它:

override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): AbstractViewHolder {
    return when (viewType) {
        LOADER -> createItem(viewGroup, R.layout.row_loader, ::LoaderViewHolder)
        DATE -> createItem(viewGroup, R.layout.row_date, ::DateViewHolder)
        else -> throw IllegalStateException("Wrong class")
    }
}
Run Code Online (Sandbox Code Playgroud)

这里LoaderViewHolderDateViewHolder是 的后代AbstractViewHolder