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

Kotlin反射递归解析结构体报错,请求技术指导

问题:Kotlin反射递归解析结构体时的构造函数错误

我正在尝试使用Kotlin的反射机制,但在递归应用解析函数时出现错误。我学习Kotlin不足一个月,对此完全无从下手,恳请技术指导。

相关代码如下:

import kotlin.reflect.KClass
import kotlin.reflect.KMutableProperty
import kotlin.reflect.full.findAnnotation

annotation class CsByte
annotation class CsStruct

class Struct1 {
    @CsByte
    var x: Int = 0
    @CsStruct
    var inner1: Inner = Inner()
}

class Inner {
    @CsByte
    var y: Int = 0
}

fun <T : Any> parseStructRecursively (type:KClass<T>): T {
    val obj = type.constructors.find { it.parameters.isEmpty() }?.call()!!
    for (field in type.members) {
        if (field.findAnnotation<CsByte>() != null)
            (field as KMutableProperty<*>).setter.call(obj, 9)
        if (field.findAnnotation<CsStruct>() != null)
            (field as KMutableProperty<*>).setter.call(obj, parseStructRecursively(field::class))
            //                                                                     ^^^^^^^^^^^^ wrong?
            // Inner::class works OK,  field::class fails because it does not have argumentless constructor.
    }
    return obj
}

inline fun <reified T : Any> parseReified (): T {
    return parseStructRecursively(T::class)
}

fun main() {
    var s1 = parseReified<Struct1>()
    println(s1.x == 9)
    println(s1.inner1.y == 9)
}

问题核心

在parseStructRecursively函数的递归调用处,使用field::class时提示无无参构造函数,而直接使用Inner::class则能正常运行。


原因分析

field::class获取的是属性对象自身的KClass(比如KMutableProperty<Inner>这个类),而非该属性所指向的实际类型Inner::class。你需要的是字段的返回值类型,也就是结构体的KClass,而不是属性对象的类。

解决方法

修改递归调用部分的代码,通过field.returnType.classifier获取字段的实际类型KClass:

修正后的完整函数

fun <T : Any> parseStructRecursively(type: KClass<T>): T {
    val obj = type.constructors.find { it.parameters.isEmpty() }?.call()!!
    for (field in type.members) {
        // 先判断当前成员是否是可变属性,避免类型转换异常
        if (field is KMutableProperty<*>) {
            if (field.findAnnotation<CsByte>() != null) {
                field.setter.call(obj, 9)
            }
            if (field.findAnnotation<CsStruct>() != null) {
                // 获取字段的实际类型KClass
                val fieldType = field.returnType.classifier as KClass<*>
                val innerStruct = parseStructRecursively(fieldType as KClass<Any>)
                field.setter.call(obj, innerStruct)
            }
        }
    }
    return obj
}

额外优化建议

  • 增加类型校验:遍历类成员时先判断是否为KMutableProperty<*>,避免对函数、不可变属性等非目标成员进行无效操作,降低运行时风险。
  • 优化空安全:原代码中!!非空断言会在类无无参构造函数时直接抛出异常,实际场景中可以添加异常捕获或返回默认值的逻辑,提升代码健壮性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 07:46:32