给定第三方库中的类,方法和参数的名称,如何使用scala反射创建对象并调用其方法?
例如,类名称为“ org.apache.spark.mllib.clustering.LDA”,方法为“ setK”,参数为3,如何使用scala反射来构造LDA对象并调用方法?结果应等于new LDA().setK(3)
。
在scala反射文档中,我找到了以下代码来构造Person对象
val m = ru.runtimeMirror(getClass.getClassLoader)
val classPerson = ru.typeOf[Person].typeSymbol.asClass
val ctor = ru.typeOf[Person].decl(ru.termNames.CONSTRUCTOR).asMethod
val ctorm = cm.reflectConstructor(ctor)
val p = ctorm("Mike")
但是如果我拥有“ Person”而不是Person类怎么办?
答案 0 :(得分:1)
尝试
import org.apache.spark.mllib.clustering.LDA
import scala.reflect.runtime.{universe => ru}
val m = ru.runtimeMirror(getClass.getClassLoader)
val classLDA = ru.typeOf[LDA].typeSymbol.asClass
val ctor = ru.typeOf[LDA].decl(ru.termNames.CONSTRUCTOR).asMethod
val cm = m.reflectClass(classLDA)
val ctorm = cm.reflectConstructor(ctor)
val p = ctorm.asInstanceOf[LDA]
p.setK(3)
答案 1 :(得分:1)
我必须同意Luis的评论,即您应该强烈考虑其他方法,但是如果确实需要这种方法,那么
// for the example
val className = "org.apache.spark.mllib.clustering.LDA"
val methodName = "setK"
val constructorParams = Array()
val params = Array(3)
// symbols
val m = ru.runtimeMirror(getClass.getClassLoader)
val classSymbol = m.staticClass(className)
val ctor = classSymbol.primaryConstructor.asMethod
// assumes the method exists and isn't overloaded
val method = classSymbol.toType.decl(ru.TermName(methodName)).asMethod
val cm = m.reflectClass(classSymbol)
val ctorm = cm.reflectConstructor(ctor)
val instance = ctorm(constructorParams: _*)
val instancem = m.reflect(instance)
val methodm = instancem.reflectMethod(method)
methodm(params: _*)
或者对于此特定任务,您可以发现使用Java反射更简单,而Scala反射并没有真正的优势:
val clazz = Class.forName(className)
val ctor = clazz.getConstructors()(0)
val instance = ctor.newInstance(constructorParams: _*)
// again, assumes the method exists and isn't overloaded
val method = clazz.getMethods().find(_.getName == methodName).get
method.invoke(instance, params: _*)