如何获取非大小写类的构造函数参数的默认值?

时间:2019-02-27 16:46:51

标签: java scala reflection

class Person(name: String, age: Int, numThings: Option[Int] = Some(15))

我可以使用Scala反射来获得像这样的case类的默认值:

   val companionType: Type = classSymbol.companion.typeSignature
   val companionObject = currentMirror.reflectModule(classSymbol.companion.asModule).instance
   val companionMirror = currentMirror.reflect(companionObject)
   val defaultValueAccessorMirror =
   if (member.typeSignature.typeSymbol.isClass) {
     val defaultValueAccessor = companionType.member(TermName("apply$default$" + (index + 1)))
     if (defaultValueAccessor.isMethod) {
       Some(companionMirror.reflectMethod(defaultValueAccessor.asMethod))
     } else {
       None
     }
   } else {
     None
   }

这将获取所生成的伴随对象中的方法,该对象在被调用时咳出默认值。可悲的是,非案例类似乎没有此功能。

如何在上面的示例中使用Scala或Java反射获取Person.numThings的默认值?

1 个答案:

答案 0 :(得分:1)

我认为通过Java反射来检索这些默认值要容易得多,而不是使这种过度复杂的Scala反射...

当编译为.class文件时,默认参数值将转换为带有名称后缀的静态方法。可以通过调用类引用上的相应方法来检索这些值。

例如,我们有一个case和一个非大小写的类:

class Person(name: String, age: Int, numThings: Option[Int] = Some(15))

case class Item(id: Long, other: String = "unknown")

首先,我们需要确定参数的顺序索引以检索其默认值。我不知道您的用例,所以假设您知道或计算了它们。对于3,它们将是Person;对于2,它们将是Item。是的,它们不是基于 0的。

这个非常短的方法检索值:

private def extractDefaultConstructorParamValue(clazz: Class[_],
                                                iParam: Int): Any = {
  val methodName = "$lessinit$greater$default$" + iParam
  clazz.getMethod(methodName).invoke(clazz)
}

致电给他们

val defParamNonCase = extractDefaultConstructorParamValue(classOf[Person], 3)
val defParamCase = extractDefaultConstructorParamValue(classOf[Item], 2)

println(defParamNonCase)
println(defParamCase)

输出

Some(15)
unknown