如何通过Java反射提取Scala类方法中参数的默认值
实现原理
Scala 编译期会为带默认值的方法参数自动生成公开的合成方法,命名规则为 原方法名$default$参数序号,参数序号从1开始计数。比如你示例中getSum方法的第二个参数y有默认值,编译后会自动生成名为getSum$default$2的无参方法,调用该方法即可拿到对应的默认值。
实现代码
import java.lang.reflect.Method // 你给出的示例类 class X { def getSum(x: Int, y: Int = 10): Int = x + y } // 提取方法参数默认值的工具方法 def getMethodDefaultParams(clazz: Class[_], methodName: String, instance: AnyRef): Map[String, Any] = { // 匹配目标方法,有重载场景可以补充参数类型校验避免匹配错误 val targetMethod = clazz.getDeclaredMethods .find(_.getName == methodName) .getOrElse(throw new NoSuchMethodException(s"类${clazz.getName}中不存在方法$methodName")) val paramNames = targetMethod.getParameters.map(_.getName) val paramCount = targetMethod.getParameterCount // 遍历所有参数位置,查找对应默认值合成方法 (1 to paramCount).flatMap { index => val defaultMethodName = s"${methodName}$$default$$$index" try { val defaultMethod = clazz.getMethod(defaultMethodName) // 实例方法需要传入类实例调用合成方法拿默认值 val defaultValue = defaultMethod.invoke(instance) Some(paramNames(index - 1) -> defaultValue) } catch { case _: NoSuchMethodException => None // 该位置参数无默认值 } }.toMap } // 测试用例 val xIns = new X() val defaultVals = getMethodDefaultParams(classOf[X], "getSum", xIns) // 输出结果为Map(y -> 10) println(defaultVals)
注意事项
- 如果要提取伴生对象内方法的默认值,传入伴生对象实例即可,伴生对象实例可以通过
Class.forName("类全限定名$").getField("MODULE$").get(null)获取 - 该规则适配Scala 2.11+所有版本,Scala 3的编译命名规则一致,也可以直接兼容
内容的提问来源于stack exchange,提问作者Kyuubi
相关产品推荐
相关产品推荐

