You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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) {}
}

说明:

  1. 在OutGeneric中通过lazy初始化块,利用反射获取当前匿名子类的泛型父类(即OutGeneric<Human>)的实际类型参数Human。
  2. 将获取到的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()) {}
}

说明:

  1. 借助inline+reified泛型,在createOutGeneric函数中直接获取T::class.java。
  2. 让匿名OutGeneric子类实现getActualType方法返回该类型,再传递给InnerGeneric使用。

内容的提问来源于stack exchange,提问作者PopKter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 13:23:24