generics - 如何在 Kotlin 中获取泛型参数类

Firebase 的 snapshot.getValue() 期望调用如下:

snapshot?.getValue(Person::class.java)

但是我想用通过类声明传递给类的通用参数替换 Person,即

class DataQuery<T : IModel> 

并使用该通用参数执行以下操作:

snapshot?.getValue(T::class.java)

但是当我尝试这样做时,我收到一条错误消息,指出

only classes can be used on the left-hand side of a class literal

是否可以像在 C# 中那样对泛型参数提供类约束,或者我可以使用其他一些语法来获取泛型参数的类型信息?

最佳答案

对于具有泛型参数 T 的类,您不能这样做,因为您没有 T 的类型信息,因为 JVM 会删除类型信息。因此这样的代码不能工作:

class Storage<T: Any> {
    val snapshot: Snapshot? = ...

    fun retrieveSomething(): T? {
        return snapshot?.getValue(T::class.java) // ERROR "only classes can be used..."
    }
}

但是,如果 T 的类型被具体化并在一个内联函数中使用,你就可以做到这一点:

class Storage {
    val snapshot: Snapshot? = ...

    inline fun <reified T: Any> retrieveSomething(): T? {
        return snapshot?.getValue(T::class.java)
    }
}

注意内联函数if public 只能访问类的公共(public)成员。但是您可以有该函数的两种变体,一种接收非内联并访问私有(private)内部的类参数,另一种内联辅助函数从推断的类型参数进行具体化:

class Storage {
    private val snapshot: Snapshot? = ...

    fun <T: Any> retrieveSomething(ofClass: Class<T>): T? {
        return snapshot?.getValue(ofClass)
    }
    
    inline fun <reified T: Any> retrieveSomething(): T? {
        return retrieveSomething(T::class.java)
    }
}

您还可以使用 KClass 代替 Class 以便仅 Kotlin 的调用者可以使用 MyClass::class 而不是 MyClass::class.java

如果希望类配合泛型上的内联方法(即Storage类只存储T类型的对象):

class Storage <T: Any> {
    val snapshot: Snapshot? = ...

    inline fun <reified R: T> retrieveSomething(): R? {
        return snapshot?.getValue(R::class.java)
    }
}

内联函数中具体类型的链接:https://kotlinlang.org/docs/reference/inline-functions.html#reified-type-parameters

https://stackoverflow.com/questions/34122450/

相关文章:

kotlin - 意外覆盖 : The following declarations have th

gradle - 如何将 Gradle 项目中 Kotlin 的字节码版本设置为 Java 8?

kotlin - 使用 Gradle 和 Kotlin 构建自执行 JAR

interface - 如何创建接口(interface)的匿名实现?

android - 无法使用 Android Studio 3.0 + DataBinding +

java - Kotlin:使用 lambda 代替函数式接口(interface)?

kotlin - 警告 : API 'variant.getPackageLibrary()' is

javascript - Kotlin JavaScript 到 TypeScript 定义文件

kotlin - 实现Java接口(interface)时如何克服 "same JVM signat

arrays - Kotlin中数据类的equals方法