Kotlin的反思:未知的类型参数
我正在对Kotlin的反思进行一些实验。
我试图用它的参数来获得一个泛型类的反射对象。
在Java中,这将是一个ParameterizedType
。
使用Java的反射API来获得这样的东西的方式有点复杂:创建一个泛型类的匿名子类,然后获得其超类型的第一个参数。
这是一个例子:
@Suppress("unused") @PublishedApi internal abstract class TypeReference<T> {} inline fun <reified T> jGeneric() = ((object : TypeReference<T>() {}).javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0]
当我println(jGeneric<List<String?>>())
,它打印java.util.List<? extends java.lang.String>
java.util.List<? extends java.lang.String>
,这是合乎逻辑的,考虑到Kotlin的List
使用声明站点差异,并且Java类型没有可空性的概念。
现在,我想达到同样的结果,但是使用Kotlin反射API(当然这将包含可空性信息)。
当然, List<String>::class
不能工作,因为它产生一个KClass
。 我正在寻找一个KType
。
但是,当我尝试这个:
inline fun <reified T> kGeneric() = (object : TypeReference<T>() {})::class.supertypes[0].arguments[0].type
当我println(kGeneric<List<String?>>())
,它打印[ERROR : Unknown type parameter 0]
,这是相当…好,反复;)
我怎么能在Kotlin中得到一个反映List<String>
的KType
?
要在Kotlin 1.1中创建KType
实例,您有两个选择:
-
要从
KClass
创建一个简单的非空类型,其中类不是泛型,或者可以用星型投影(*
)替换其所有类型参数,请使用starProjectedType
属性。 例如,下面的代码创建一个表示非空类型String
的KType
:val nonNullStringType = String::class.starProjectedType
或者,下面的代码创建一个表示不可为空的类型
List<*>
的KType
:val nonNullListOfSmth = List::class.starProjectedType
-
对于更复杂的情况,请使用
createType
函数。 它需要类,类型参数以及类型是否可以为空。 类型参数是KTypeProjection
的列表,它只是一个类型+方差(in / out / none)。 例如,下面的代码创建一个代表List<String>
的KType
实例:val nonNullStringType = String::class.starProjectedType val projection = KTypeProjection.invariant(nonNullStringType) val listOfStrings = listClass.createType(listOf(projection))
或者,下面创建类型
List<String>?
:val listOfStrings = listClass.createType(listOf(projection), nullable = true)
starProjectedType
和createType
都在包kotlin.reflect.full
中定义。
我们打算引入一个简单的从一个内联函数的特定类型参数获取一个KType
实例的可能性,这将有助于在某些情况下所需的类型是静态的,但是目前还不能完全清楚这是否可能,而没有大的开销。 因此,在实施之前,请使用上述说明。
- 如何在空Kotlin数组上调用reduce?
- 什么时候应该使用let {},什么时候只是简单的!= null
- Kotlin android数据库:不能将java.lang.String强制转换为android.database.Cursor
- ArgumentCaptor vs InOrder来validation后续的回调与不同的参数
- 在Kotlin的toString()中包含在data类的主体中声明的属性
- 创建和发布Kotlin库以避免多个运行时问题的正确方法是什么?
- Gson与Kotlin嵌套的类
- Kotlin在Android上使用MultiDex进行授权,低于21
- 有没有办法在kotlin轻松打开和关闭流?