Kotlin中如何获取Any类型反射对象的BigDecimal属性值?
解决Any类型对象遍历成员属性并转换为BigDecimal的类型错误
问题重现
编写如下代码尝试遍历Any类型对象的成员属性,并将属性值转换为BigDecimal?:
fun validate(obj1: Any) { // 获取对象的KClass val objKClass = obj1::class // 使用KClass转换对象 val obj1Cast = objKClass.safeCast(obj1) // 遍历成员属性 for (prop in objKClass.memberProperties) { // 尝试转换为BigDecimal? val bigDecimal: BigDecimal? = prop.get(obj1Cast) as BigDecimal? } }
运行时在prop.get(obj1Cast)处触发类型错误:
Type mismatch. Required: Nothing Found: Any?
报错原因
obj1::class返回的KClass类型是KClass<out Any>,调用safeCast(obj1)时,由于泛型协变特性,返回值被推断为Nothing?。而memberProperties中的KProperty的get方法需要接收属性所属类的实例作为参数,Nothing?无法匹配该参数类型,从而引发类型不匹配错误。
可行解决方案
方案1:直接使用原对象调用get方法
不需要额外的safeCast转换,直接传入原对象obj1即可,因为obj1本身就是该属性所属类的实例,符合get方法的参数要求:
import java.math.BigDecimal import kotlin.reflect.full.memberProperties fun validate(obj1: Any) { val objKClass = obj1::class for (prop in objKClass.memberProperties) { // 使用as?替代as,避免类型转换异常 val bigDecimal: BigDecimal? = prop.get(obj1) as? BigDecimal } }
方案2:先判断属性类型再转换(更安全)
先检查属性的返回类型是否属于BigDecimal,再执行转换,减少无效转换和异常风险:
import java.math.BigDecimal import kotlin.reflect.full.memberProperties import kotlin.reflect.full.starProjectedType fun validate(obj1: Any) { val objKClass = obj1::class for (prop in objKClass.memberProperties) { // 判断属性返回类型是否为BigDecimal的子类型 if (prop.returnType.isSubtypeOf(BigDecimal::class.starProjectedType)) { val bigDecimal: BigDecimal? = prop.get(obj1) as BigDecimal? } } }
内容的提问来源于stack exchange,提问作者buzoherbert
相关产品推荐
相关产品推荐

