朋友!
我是Kotlin的新手,现在有个问题。
现在我想在OneClass中获得泛型类型T,下面是一些外围代码。
// IDatabase.kt
package com.ra
abstract class IDatabase<T> { }
// Database1.kt
import kotlin.reflect.jvm.javaType
open class Database1<T>: IDatabase<T>() {
val tClass = this::class.supertypes[0].arguments[0].type!!.javaType as Class<T>
}
// Database2.kt
import kotlin.reflect.jvm.javaType
open class Database2<T>: IDatabase<T>() {
val tClass = this::class.supertypes[0].arguments[0].type!!.javaType as Class<T>
// just wrap a `object` to confort the user
companion object {
fun <T> getInstance(): Database2<T> {
return object: Database2<T>() {}
}
}
}
下面是主要的函数,在这里我测试了三种获得泛型T的方法,结果都在代码下面的注释中。
fun main(args: Array<String>) {
val database1 = Database1<String>()
println(database1.tClass.canonicalName)
/**
* Exception in thread "main" java.lang.ClassCastException:
* sun.reflect.generics.reflectiveObjects.TypeVariableImpl cannot be cast to java.lang.Class
* at com.ra.Database1.<init>(Database1.kt:6)
* at com.ra.MainKt.main(Main.kt:4)
*/
val database2 = object: Database1<String>() {}
print(database2.tClass.canonicalName)
/**
* java.lang.String
*/
val database3 = Database2.getInstance<String>()
println(database3.tClass.canonicalName)
/**
* Exception in thread "main" java.lang.ClassCastException:
* sun.reflect.generics.reflectiveObjects.TypeVariableImpl cannot be cast to java.lang.Class
* at com.ra.Database2.<init>(Database2.kt:6)
* at com.ra.Database2$Companion$getInstance$1.<init>(Database2.kt:10)
* at com.ra.Database2$Companion.getInstance(Database2.kt:10)
* at com.ra.MainKt.main(Main.kt:19)
*/
}
正如你所看到的,只有一种成功的方式——方式2。但一点也不漂亮。由于我想将其包装在一个静态函数中(就像方式3所做的那样),它再次失败。
下面是我的问题:
-
为什么会出错
ClassCastException
发生
-
有没有更好的方法来解决这个问题?如果喜欢C#'s解决方案,那就太好了。
-
我知道问题的原因是JVM在编译期间擦除了泛型类型,所以我想知道(出于好奇)这种情况何时才能改变?或者Kotlin或其他JVM语言可能会记录泛型类型信息?如果有,请告诉我。我已经受够了字型擦除。。。