问题
I am trying to call a function using a variable as String type dynamically i.e. variable will contain a function name as String. So, I need to call a function using that variable.
So, I am using Scala Reflection. It is working if the function is accepting datatype as Sting, But it is throwing error List[Map[String, Double]]
I used below link to refer a code
Is there any Scala feature that allows you to call a method whose name is stored in a string?
and below is a test program which I am trying to test
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)
}
}
My scala version is 2.11.6 and I am using IntelliJ. I have checked the SDK version also. And unchecked the "Run worksheet in the compile process" under scala
But still no luck! Any idea will be helpful. Thanks!
回答1:
As described here Runtime Classes in Java vs. Runtime Types in Scala
using Java reflection on Scala classes might return surprising or incorrect results
It seems for your case, as data is of type scala.collection.immutable.List, you need to use Scala reflection to get the type of the data val at runtime. Here is an example
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]
}
回答2:
I give a workable solution below that employs scala reflection vs the java/scala hybrid of @ValentinCarnu.
I am not a reflection guru, and so I do not know if the below is idiomatic.
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)
}
}
来源:https://stackoverflow.com/questions/53044552/java-lang-nosuchmethodexception-scala-collection-immutable-coloncolon