从kotlin

时间:2018-05-26 06:06:03

标签: kotlin kotlin-reflect

我有一个像这样构建的val

val qs = hashMapOf<KProperty1<ProfileModel.PersonalInfo, *> ,Question>()

如何从此变量中获取 ProfileModel.PersonalInfo 的类?

换句话说,什么表达式(当然涉及qs)应该替换 Any 以便该测试通过。

@Test
fun obtaionResultTypeFromQuestionList(){
    val resultType = Any()
    assertEquals(ProfileModel.PersonalInfo::class, resultType)
}

感谢您的关注

1 个答案:

答案 0 :(得分:3)

由于Java type erasure,没有直接获取此类信息的方法。 简而言之 - 所有关于泛型的信息(在您的情况下)在运行时都不可用,HashMap<String, String>变为HashMap

但是如果在JVM级别上进行一些更改,比如定义新类,则会保留有关实际类型参数的信息。它让你有能力做这样的黑客攻击:

val toResolve = object : HashMap<KProperty1<ProfileModel.PersonalInfo, *> ,Question>() {
    init {
        //fill your data here
    }
}

val parameterized = toResolve::class.java.genericSuperclass as ParameterizedType
val property = parameterized.actualTypeArguments[0] as ParameterizedType
print(property.actualTypeArguments[0])

打印ProfileModel.PersonalInfo

说明:

  1. 我们定义新的匿名类会影响JVM级别,而不仅仅是运行时,因此保留有关通用的信息
  2. 我们获得了新的匿名类实例的通用超类,结果是HashMap< ... , ... >
  3. 我们得到第一个传递给HashMap通用括号的类型。它为我们提供了KProperty1< ... , ... >
  4. 使用KProperty1
  5. 执行上一步

    Kotlin与JVM类型擦除以及Java一样。通过将哈希映射的创建移动到单独的函数,可以使代码更好一些:

    inline fun <reified K, reified V> genericHashMapOf(
            vararg pairs: Pair<K, V>
    ): HashMap<K, V> = object : HashMap<K, V>() {
        init {
            putAll(pairs)
        }
    }
    
    ...
    
    val hashMap = genericHashMapOf(something to something)