使用反射访问 Amazon Deequ 中的方法

Using reflections to access methods in Amazon Deequ

我计划创建一个用户配置文件,稍后我将解析该文件以便 运行 来自 Amazon Deequ 的一些检查。我希望能够从配置文件中传递字符串名称来获取方法;然而,在我尝试这样做的过程中,我一直遇到障碍。

import com.amazon.deequ.checks._

val ru = scala.reflect.runtime.universe
val rm = ru.runtimeMirror(getClass.getClassLoader)

val myClass = new Check(CheckLevel.Error, "unit testing my data")
val im = rm.reflect(myClass)

val methodSymbolNonNeg = ru.typeOf[Check].decl(ru.TermName("isNonNegative")).asMethod
val methodNonNeg = im.reflectMethod(methodSymbolNonNeg)

Name: Compile Error
Message: <console>:48: error: type mismatch;
 found   : ru.MethodSymbol
 required: ru.MethodSymbol
       val methodNonNeg = im.reflectMethod(methodSymbolNonNeg)

我尝试了文档中的几个示例以及我在 SO 上找到的示例。我还检查了 class myClass.getClass.getMethods.map(_.getName).foreach{println} 以及 Github.

中的方法名称

此外,我也尝试过使用 .getClass.getMethod 并调用该方法

val m = myClass.getClass.getMethod("isNonNegative", "".getClass, 2.13.getClass, Option("").getClass)

Name: java.lang.NoSuchMethodException
Message: com.amazon.deequ.checks.Check.isNonNegative(java.lang.String, double, scala.Some)
StackTrace:   at java.lang.Class.getMethod(Class.java:1786)

无法重现您的 Scala 反射代码中的编译错误。 使用 Scala 2.13.3 + Deequ 1.0.5 和 Scala 2.11.12 + Deequ 1.0.5,您的代码可以编译。 编写您的依赖项和 Scala 版本。尝试 clean 重建您的项目(例如 sbt clean compile 如果您使用 sbt 构建项目)。

Deequ 1.0.5 依赖于 Scala 2 的 Scala 库版本(Shapeless、Twitter Chill、Spark、json4s、scala-parser-combinators、scala-xml、Breeze、Spire、Machinist)11.x 所以你应该使用 Scala 2.11.x.

使用 Scala 2.13 我有 java.lang.NoClassDefFoundError: scala/Serializable.

还要注意在https://github.com/awslabs/deequ处写着

Deequ depends on Java 8 and is known to work with Apache Spark versions 2.2.x to 2.4.x.

你的编译错误 found: ru.MethodSymbol, required: ru.MethodSymbol 看起来像是依赖版本的问题。

关于您的 Java 反射代码,您刚刚错误地指定了 类 方法参数。 Check#isNonNegative的签名是

def isNonNegative(
  column: String,
  assertion: Double => Boolean,
  hint: Option[String])
: CheckWithLastConstraintFilterable

所以你应该这样做

myClass.getClass.getMethod("isNonNegative", classOf[String], classOf[Double => Boolean], classOf[Option[_]])

顺便说一下,混合使用 Scala 反射和 Java 反射很奇怪。