Kotlin:如何在运行时在OneClass 中获得实际的genericstypesT.

朋友们! 我是Kotlin的绿手,现在这是一个问题。 现在我想在OneClass中获得genericstypesT,下面是一些外围代码。

// IDatabase.kt package com.ra abstract class IDatabase { } 
 // Database1.kt import kotlin.reflect.jvm.javaType open class Database1: IDatabase() { val tClass = this::class.supertypes[0].arguments[0].type!!.javaType as Class } 
 // Database2.kt import kotlin.reflect.jvm.javaType open class Database2: IDatabase() { val tClass = this::class.supertypes[0].arguments[0].type!!.javaType as Class // just wrap a `object` to confort the user companion object { fun  getInstance(): Database2 { return object: Database2() {} } } } 

下面是主要的function,我测试了三种方法来获得genericstypesT,结果在每个代码下面的注释中。

 fun main(args: Array) { val database1 = Database1() 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.(Database1.kt:6) * at com.ra.MainKt.main(Main.kt:4) */ val database2 = object: Database1() {} print(database2.tClass.canonicalName) /** * java.lang.String */ val database3 = Database2.getInstance() 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.(Database2.kt:6) * at com.ra.Database2$Companion$getInstance$1.(Database2.kt:10) * at com.ra.Database2$Companion.getInstance(Database2.kt:10) * at com.ra.MainKt.main(Main.kt:19) */ } 

正如你所看到的,只有一种成功的方式 – 方式2.但是,它不是很好。 因为我想把它封装在一个静态函数中(就像3),它又失败了。

所以这是我的问题:

  1. 为什么ClassCastException发生错误?
  2. 有更多漂亮的方法来解决这个问题吗? 如果像C#的解决方案将是伟大的。
  3. 我知道问题的原因是JVM在编译期间擦除generics,所以我想知道(只是好奇)什么时候可以更改? 或者也许Kotlin或其他JVM语言可能会记录通用types信息? 如果有任何请告诉我。 我已经足够的types擦除…

它可以使用一个指定的内联函数

 package com.ba import kotlin.reflect.KClass abstract class IDatabase { } open class Database2(val tClass: KClass) : IDatabase() { // just wrap a `object` to confort the user companion object { inline fun  getInstance(): Database2 = Database2(T::class) } } fun main(args: Array) { val databaseString = Database2.getInstance() println(databaseString.tClass) val databaseInt = Database2.getInstance() println(databaseInt.tClass) } 

输出

 class kotlin.String class kotlin.Int