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

Kotlin中如何遍历泛型类型参数T对应类的成员属性及值

问题核心原因

JVM 存在泛型类型擦除机制,默认情况下运行时会抹除泛型参数的实际类型信息,所以直接写 T::class.java.members.forEach{} 这类代码默认无法通过编译。你可以通过两种方案实现遍历需求:


方案1:inline函数 + 实化类型参数(推荐优先使用)

reified 关键字可以让 inline 函数的泛型参数在编译时被实化,运行时直接拿到泛型的实际类型信息,无需额外传参:

class DoStuff {
    // 给方法添加inline修饰,泛型参数前加reified关键字
    inline fun <reified T> performAction(args: T) {
        // 校验入参必须是data class,不符合直接抛出异常
        require(T::class.isData) { "仅支持传入data class类型的参数" }
        
        T::class.members.forEach { prop ->
            // 处理私有属性访问权限
            prop.isAccessible = true
            // 输出属性名 + 对应实例的属性值
            println("${prop.name} = ${prop.call(args)}")
        }
    }
}

// 调用示例
data class Person(var info: String, var age: Int)
val doer = DoStuff()
doer.performAction(Person("学生", 18))

该方案的限制是:reified 关键字只能修饰函数的泛型参数,不能修饰类的泛型参数,且 public 的 inline 函数无法访问类的私有成员。


方案2:构造类时传入类型类实例

如果你的 DoStuff 类需要固定绑定某一种泛型类型,可以在构造类的时候手动传入对应类型的 KClass 实例保存类型信息:

// 构造函数接收KClass参数存储泛型类型信息
class DoStuff<T>(private val clazz: KClass<T>) {
    fun performAction(args: T) {
        require(clazz.isData) { "仅支持传入data class类型的参数" }
        
        clazz.members.forEach { prop ->
            prop.isAccessible = true
            println("${prop.name} = ${prop.call(args)}")
        }
    }
}

// 调用示例
data class Person(var info: String, var age: Int)
// 初始化类的时候传入对应data class的KClass
val personDoer = DoStuff(Person::class)
personDoer.performAction(Person("上班族", 28))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 20:45:04