java.lang.NoSuchMethodException: scala.collection.immutable.$colon$colon
Я пытаюсь вызвать функцию, используя переменную как тип String, динамически, т.е. переменная будет содержать имя функции как String. Итак, мне нужно вызвать функцию с использованием этой переменной.
Итак, я использую Scala Reflection. Работает, если функция принимает тип данных как Sting, но выдает ошибку List[Map[String, Double]]
Я использовал ссылку ниже, чтобы ссылаться на код
и ниже тестовая программа, которую я пытаюсь проверить
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
Но все равно не повезло! Любая идея будет полезна. Спасибо!
2 ответа
Как описано здесь, классы времени выполнения в Java и типы времени выполнения в Scala
использование отражения Java на классах Scala может привести к неожиданным или неверным результатам
Кажется, для вашего случая, поскольку данные имеют тип scala.collection.immutable.List, вам нужно использовать отражение Scala, чтобы получить тип данных 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]
}
Ниже я приведу работоспособное решение, которое использует отражение scala против гибридного java/scala @ValentinCarnu.
Я не гуру рефлексии, и поэтому я не знаю, является ли нижеследующее идиоматическим.
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)
}
}