Kotlin的反射:未知类型参数

4

我正在对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>,这是合理的,考虑到Kotlin的List使用声明处out变型且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 ?


"[ERROR : ...]"这部分是toString方法实现中的一个错误:https://youtrack.jetbrains.com/issue/KT-17103 - Alexander Udalov
1个回答

11

在Kotlin 1.1中创建KType实例有两种选项:

  • 要从KClass创建一个简单的非空类型,其中类既非泛型,也可以用星投影(*)替换其所有类型参数,请使用starProjectedType属性。例如,以下代码创建一个KType,表示非空类型String

    val nonNullStringType = String::class.starProjectedType
    

    或者,以下内容创建一个表示非空类型 List<*>KType:

    val nonNullListOfSmth = List::class.starProjectedType
    
  • 对于更复杂的情况,请使用createType函数。 它接受类、类型参数以及类型是否应该可为空。 类型参数是一个KTypeProjection列表,它仅仅是一个类型和方差(协变/逆变/不变)。例如,以下代码创建了一个表示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)
    

starProjectedTypecreateType 都在 kotlin.reflect.full 包中定义。

我们计划引入从内联函数的具体类型参数中简单获取 KType 实例的可能性,在某些需要静态已知类型的情况下会有所帮助,但目前还不清楚是否能够做到没有重大开销。因此,在该功能实现之前,请使用上面解释的声明。


不幸的是,这个答案强制手动创建类型,这使得它无法在库中使用。 我会关注您链接的问题...谢谢;) - Salomon BRYS
我认为在1.1版本中,像上面那样创建类型并不能在所有情况下使用,因为有一些方面尚未实现。defaultType仍然需要解决这些错误。也许@udalov可以评论一下是否已经解决了这个问题。 - Jayson Minard
@JaysonMinard,你具体指的是哪些错误和方面? - Alexander Udalov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接