Scala 反射:如何在给定 'String-type' class 名称和方法名称的情况下构造对象和 运行 其方法?
Scala reflection: How to construct object and run its methods given 'String-type' class name and method name?
给定一个class的名称,方法和来自第三方库的参数,如何使用scala反射创建一个对象并调用它的方法?
例如class名称为"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 class 怎么办?
尝试
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)
我必须同意 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: _*)
给定一个class的名称,方法和来自第三方库的参数,如何使用scala反射创建一个对象并调用它的方法?
例如class名称为"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 class 怎么办?
尝试
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)
我必须同意 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: _*)