如何在Kotlin中获得generics参数类

Firebase的snapshot.getValue()预计将被调用,如下所示:

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

不过,我想用一个通过类声明传递给类的generics参数替换Person

 DataQuery 

并使用该generics参数来做这样的事情:

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

但是当我尝试,我得到一个错误说明

只有类可以用在类文字的左侧

是否有可能像在C#中的generics参数提供一个类的约束,还是有一些其他的语法,我可以用来获取generics参数的types信息?

你需要的是通用参数的修饰符,你可以在这里阅读。 https://kotlinlang.org/docs/reference/inline-functions.html#reified-type-parameters所以,如果你做这样的事情:

 inline fun T.logTag() = T::class.java.simpleName 

你将得到实际的调用者类的名字,而不是“对象”。

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

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

但是,如果T的types在内联函数中被指定和使用,则可以使其工作:

 class Storage { val snapshot: Snapshot? = ... inline fun  retrieveSomething(): T? { return snapshot?.getValue(T::class.java) } } 

请注意,内联函数如果公开只能访问该类的公共成员。 但是可以有两个函数变体,一个接收一个不是内联的类参数,并且访问私有内部函数,另一个内联辅助函数从推断的types参数中进行确定:

 class Storage { private val snapshot: Snapshot? = ... fun  retrieveSomething(ofClass: Class): T? { return snapshot?.getValue(ofClass) } inline fun  retrieveSomething(): T? { return retrieveSomething(T::class.java) } } 

您也可以使用KClass而不是Class这样只有Kotlin的调用者才可以使用MyClass::class而不是MyClass::class.java

如果您希望类与generics上的内联方法配合使用(意味着类Storage只存储typesT对象):

 class Storage  { val snapshot: Snapshot? = ... inline fun  retrieveSomething(): R? { return snapshot?.getValue(R::class.java) } } 

内联函数中通用types的链接: https : //kotlinlang.org/docs/reference/inline-functions.html#reified-type-parameters