我正在尝试使用变量作为String类型的动态调用函数,即变量将包含一个函数名称为String。因此,我需要使用该变量来调用函数。
因此,我正在使用Scala反射。如果函数接受数据类型为Sting,则可以正常工作,但会引发错误List [Map [String,Double]]
我在下面的链接中引用了代码
Is there any Scala feature that allows you to call a method whose name is stored in a string?
和下面是我要测试的测试程序
package test
import scala.collection.immutable.Map
class DynamicaVariable {
def cat(s1: List[Map[String, Double]]) = {
println(s1)
}
}
object DynamicaVariable{
def main(args: Array[String]): Unit = {
val obj = new DynamicaVariable
val data = List(
Map("a" -> 1.0, "b" -> 267.0, "c" -> 26.0, "d" -> 2.0), Map("a" -> 1.0, "b" -> 2678.0, "c" -> 40.0, "d" -> 2.0), Map("a" -> 4.0, "b" -> 267.0, "c" -> 26.0, "d" -> 2.0), Map("a" -> 1.0, "b" -> 2678.0, "c" -> 90.0, "d" -> 17.0)
)
val functionName = "cat"
val method = obj.getClass.getMethod(functionName,data.getClass)
method.invoke(obj,data)
}
}
我的scala版本是2.11.6,我正在使用IntelliJ。我也检查了SDK版本。并取消选中scala下的“在编译过程中运行工作表”
但是仍然没有运气!任何想法都会有所帮助。谢谢!
答案 0 :(得分:1)
如此处Runtime Classes in Java vs. Runtime Types in Scala
所述在Scala类上使用Java反射可能会返回令人惊讶或错误的结果
在您的情况下,由于 data 的类型为 scala.collection.immutable.List ,因此您需要使用Scala反射来获取 data val在运行时。这是一个例子
import scala.reflect.ClassTag
import scala.reflect.classTag
class DynamicaVariable {
def cat(s1: List[Map[String, Double]]) = {
println(s1)
}
}
object DynamicaVariable{
def main(args: Array[String]): Unit = {
val obj = new DynamicaVariable
val data = List(Map("a" -> 1.0, "b" -> 267.0, "c" -> 26.0, "d" -> 2.0)
, Map("a" -> 1.0, "b" -> 2678.0, "c" -> 40.0, "d" -> 2.0)
, Map("a" -> 4.0, "b" -> 267.0, "c" -> 26.0, "d" -> 2.0)
, Map("a" -> 1.0, "b" -> 2678.0, "c" -> 90.0, "d" -> 17.0))
val functionName = "cat"
val method = obj.getClass.getMethod(functionName, getClassOf(data).runtimeClass)
method.invoke(obj,data)
}
def getClassOf[T: ClassTag](obj: T) = classTag[T]
}
答案 1 :(得分:0)
我在下面提供了一个可行的解决方案,该解决方案使用了 scala反射与@ValentinCarnu的java / scala混合。
我不是反思大师,所以我不知道以下内容是否惯用。
import scala.collection.immutable.Map
import scala.reflect.runtime.{universe => ru}
class DynamicaVariable {
def cat(s1: List[Map[String, Double]]) = {
println(s1)
}
}
object DynamicaVariable {
def main(args: Array[String]): Unit = {
val obj = new DynamicaVariable
val data = List(
Map("a" -> 1.0, "b" -> 267.0, "c" -> 26.0, "d" -> 2.0),
Map("a" -> 1.0, "b" -> 2678.0, "c" -> 40.0, "d" -> 2.0),
Map("a" -> 4.0, "b" -> 267.0, "c" -> 26.0, "d" -> 2.0),
Map("a" -> 1.0, "b" -> 2678.0, "c" -> 90.0, "d" -> 17.0)
)
val functionName = "cat"
val mirror = ru.runtimeMirror(getClass.getClassLoader)
val instanceMirror: ru.InstanceMirror = mirror.reflect(obj)
val classSymbol = mirror.classSymbol(obj.getClass)
val termName: ru.MethodSymbol = classSymbol.info.decl(ru.TermName(functionName)).asMethod
val methodMirror: ru.MethodMirror = instanceMirror.reflectMethod(termName)
methodMirror.apply(data)
}
}