关于android:如何在Kotlin中获取泛型类型参数的类

How to get class of generic type parameter in Kotlin

我想从通用类型T获取class属性。
我已决定扩展到Any,但出现错误。
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-any/index.html#extension-properties

我有以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class FirebaseDBRepo<T : Any>(val child:String) {

private var callback: FirebaseDatabaseRepositoryCallback< T >? = null
private val ref: DatabaseReference
private val listener = object : ValueEventListener {
    override fun onDataChange(dataSnapshot: DataSnapshot) {

        //T::class.java is showing the error cannot use t as reified type parameter use class instead

        val gameDS = dataSnapshot.getValue(T::class.java)
        callback!!.onSuccess(gameDS!!)
    }

    override fun onCancelled(databaseError: DatabaseError) {

    }
}

init {
    ref = FirebaseDatabase.getInstance().reference.child(child)
}


fun addListener(callback: FirebaseDatabaseRepositoryCallback< T >) {
    this.callback = callback
    ref.addValueEventListener(listener)
}

fun removeListener() {
    ref.removeEventListener(listener)
}

}

您只能在类化变量上获取该类。在Java中发生相同的事情,但消息略有不同:

1
2
3
public < T > void x(){
    T t = T.class.newInstance();
}

在Java中,您可以这样解决:

1
2
3
public < T > void x(Class< T > cls){
    T t = cls.newInstance();
}

同样适用于Kotlin和任何电话。在大多数情况下,您需要获取一个类实例。但是,Kotlin仅使用内联泛型函数支持使用关键字的通用泛型。您可以传递一个类,但是在函数中,仅使用reified关键字确实很容易。

因为您无法使用泛型泛型声明类,所以这是无效的:

1
class SomeClass<reified T>

但是对于内联函数有效,这意味着您可以执行:

1
inline fun <reified T> someFunction()

因此,您有两个选择。但是,由于您扩展了侦听器,因此没有将泛型添加到函数的第一个选项。您不能使用泛型覆盖非泛型方法。它不会编译。

哪个离开了第二个选项,不幸的是,它很黑。将类传递给构造函数。所以它应该像这样:

1
class FirebaseDBRepo<T : Any>(val child: String, private val cls: Class< T >) {

现在,我不使用Firebase,所以不知道您要传递哪些类,因此对于下一个示例,我仅使用String

Kotlin支持某种类型的最小化,而无需使用原始类型。这:

1
val t = FirebaseDBRepo<String>("", String::class.java)

可以缩写为:

1
val t = FirebaseDBRepo("", String::class.java)

在两种情况下的推断类型均为FirebaseDBRepo<String>


由于您正在JVM上运行,因此类型擦除是一件很重要的事情。
这意味着(以简化的方式),在编译期间,泛型将被简单地忽略。因此,您无法获得T的类,因为JVM甚至都不知道" T "是什么意思。

Kotlin在某些情况下使用巧妙的技巧来解决此限制。使用内联函数时,编译器不会调用您定义的函数,而是将整个主体复制到您调用它的位置。这仅适用于内联函数。不是类。

有一个艰难的解决方法:只需添加private val classT: Class<T>
到构造函数并改为使用参数!