How to get class of generic type parameter in Kotlin
我想从通用类型
我已决定扩展到
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,所以不知道您要传递哪些类,因此对于下一个示例,我仅使用
Kotlin支持某种类型的最小化,而无需使用原始类型。这:
1 | val t = FirebaseDBRepo<String>("", String::class.java) |
可以缩写为:
1 | val t = FirebaseDBRepo("", String::class.java) |
在两种情况下的推断类型均为
由于您正在JVM上运行,因此类型擦除是一件很重要的事情。
这意味着(以简化的方式),在编译期间,泛型将被简单地忽略。因此,您无法获得T的类,因为JVM甚至都不知道" T "是什么意思。
Kotlin在某些情况下使用巧妙的技巧来解决此限制。使用内联函数时,编译器不会调用您定义的函数,而是将整个主体复制到您调用它的位置。这仅适用于内联函数。不是类。
有一个艰难的解决方法:只需添加
到构造函数并改为使用参数!