Scala反射访问Case Class属性遇问题:equals无效等咨询
Scala Case Class 属性处理问题解答
问题1:equals判断无效
你是把MethodSymbol对象直接和字符串"value id"比较,两者类型完全不同,自然不相等。要判断属性名,得先提取MethodSymbol的名称字符串:
// 正确判断逻辑:先取属性名再比较 val res1 = z.map(x => if(x.name.toString == "id") "xxx" else x.name.toString)
如果要避免不同类同名属性的冲突,可以用x.fullName(比如"Z.id")做精确匹配。
问题2:replace方法无法使用
replace是String类的方法,而你的列表元素是MethodSymbol类型,必须先把元素转换为字符串再调用该方法:
// 示例:将属性名中的"1"替换为"_one" val res2 = z.map(x => x.name.toString.replace("1", "_one"))
问题3:获取可正常处理的普通List(如List[String])
当前res1被推断为List[Object],是因为map操作中同时返回了String和MethodSymbol两种类型,被向上统一为Object。要得到统一类型的List,需将所有元素转换为String:
// 获取纯属性名组成的List[String] val attributeNames: List[String] = z.map(_.name.toString) // 带替换逻辑的处理示例 val processedNames: List[String] = z.map(x => if(x.name.toString == "id") "xxx" else x.name.toString )
问题4:不使用反射的实现示例
Scala的Case Class默认实现了Product特质,自带属性遍历能力,无需反射:
Scala 2.13+ 版本(推荐)
用productElementNames直接获取属性名:
case class Z(a1: String, b1: String, id: Integer) // 直接提取属性名列表 val attributeNames = Z("", "", 0).productElementNames.toList // 属性名替换示例 val processedNames = attributeNames.map(name => if(name == "id") "xxx" else name)
兼容旧版本Scala
用productArity结合productElementName获取属性名:
case class Z(a1: String, b1: String, id: Integer) val zInstance = Z("", "", 0) val attributeNames = (0 until zInstance.productArity) .map(zInstance.productElementName) .toList
内容的提问来源于stack exchange,提问作者Ged
相关产品推荐
相关产品推荐

