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
相关产品推荐
相关产品推荐

