如何在Kotlin内部类InnerGeneric中获取泛型T的实际类型?
问题原因与修复方案
问题根源
你遇到的问题是JVM泛型类型擦除导致的:
OutGeneric中的innerGeneric是基于泛型参数T创建的匿名InnerGeneric子类,运行时JVM无法保留这个T的实际类型信息——因为OutGeneric本身的泛型参数T在编译后会被擦除,所以InnerGeneric通过反射拿到的只是占位符T,而非具体的Human类型。
修复方案
核心思路是:在OutGeneric的具体子类(比如main中创建的匿名子类)层面先获取到实际的泛型类型,再传递给InnerGeneric使用。
方案一:通过反射在OutGeneric中获取实际类型并传递
修改后的完整代码:
import java.lang.reflect.ParameterizedType fun main() { val outGeneric = object : OutGeneric<Human>() {} outGeneric.innerGeneric.parameter() } open class Human(val name: String = "Bob") abstract class InnerGeneric<in T : Human>(private val actualType: Class<T>) { fun parameter() { println(actualType.simpleName) // 输出:Human } } abstract class OutGeneric<in T : Human> { // 懒加载获取当前OutGeneric子类的泛型实际类型 private val targetType: Class<T> by lazy { val superType = javaClass.genericSuperclass as ParameterizedType superType.actualTypeArguments[0] as Class<T> } val innerGeneric = object : InnerGeneric<T>(targetType) {} }
说明:
- 在OutGeneric中通过
lazy初始化块,利用反射获取当前匿名子类的泛型父类(即OutGeneric<Human>)的实际类型参数Human。 - 将获取到的
Class<Human>传递给InnerGeneric的构造函数,InnerGeneric直接使用这个Class对象就能拿到实际类型名称。
方案二:利用reified泛型简化类型获取
如果不想用反射,可以借助Kotlin的reified泛型特性,通过inline函数创建OutGeneric实例:
import java.lang.reflect.ParameterizedType inline fun <reified T : Human> createOutGeneric(): OutGeneric<T> { return object : OutGeneric<T>() { override fun getActualType(): Class<T> = T::class.java } } fun main() { val outGeneric = createOutGeneric<Human>() outGeneric.innerGeneric.parameter() } open class Human(val name: String = "Bob") abstract class InnerGeneric<in T : Human>(private val actualType: Class<T>) { fun parameter() { println(actualType.simpleName) // 输出:Human } } abstract class OutGeneric<in T : Human> { abstract fun getActualType(): Class<T> val innerGeneric = object : InnerGeneric<T>(getActualType()) {} }
说明:
- 借助
inline+reified泛型,在createOutGeneric函数中直接获取T::class.java。 - 让匿名OutGeneric子类实现
getActualType方法返回该类型,再传递给InnerGeneric使用。
内容的提问来源于stack exchange,提问作者PopKter
相关产品推荐
相关产品推荐

