java.lang.NoSuchMethodException: scala.collection.immutable. $ colon $ colon - PullRequest
0 голосов
/ 29 октября 2018

Я пытаюсь динамически вызывать функцию, используя переменную типа String, т.е. переменная будет содержать имя функции как String. Итак, мне нужно вызвать функцию с использованием этой переменной.

Итак, я использую Scala Reflection. Работает, если функция принимает тип данных как Sting, но выдает ошибку List [Map [String, Double]]

Я использовал ссылку ниже для обозначения кода

Существует ли какая-либо функция Scala, позволяющая вызывать метод, имя которого хранится в строке?

и ниже - тестовая программа, которую я пытаюсь проверить

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 ]

0 голосов
/ 29 октября 2018

Ниже я приведу работоспособное решение, в котором используется отражение от 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)
  }
}
0 голосов
/ 29 октября 2018

Как описано здесь Классы времени выполнения в Java и типы времени выполнения в Scala

использование отражения Java в классах Scala может привести к неожиданным или неверным результатам

В вашем случае, похоже, что data имеет тип 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]
}
...