【问题标题】:java.lang.NoSuchMethodException: scala.collection.immutable.$colon$colonjava.lang.NoSuchMethodException: scala.collection.immutable.$colon$colon
【发布时间】:2018-10-29 11:27:58
【问题描述】:

我正在尝试使用变量作为字符串类型动态调用函数,即变量将包含函数名称作为字符串。所以,我需要使用该变量调用一个函数。

所以,我正在使用 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下的“在编译过程中运行工作表”

但还是没有运气!任何想法都会有所帮助。谢谢!

【问题讨论】:

  • 不确定是否有帮助,但以这种方式调用 getMethod val method = obj.getClass.getMethod(functionName, classOf[List[Map[String, Double]]]) 对我有用

标签: java scala intellij-idea sbt scala-reflect


【解决方案1】:

如此处所述Runtime Classes in Java vs. Runtime Types in Scala

在 Scala 类上使用 Java 反射可能会返回令人惊讶或不正确的结果

对于您的情况,由于 datascala.collection.immutable.List 类型,因此您需要使用 Scala 反射来获取 的类型>data 运行时的值。这是一个例子

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】:

    我在下面给出了一个可行的解决方案,它使用 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)
      }
    }
    
    猜你喜欢
    • 1970-01-01
    • 2019-03-22
    • 1970-01-01
    • 2020-02-15
    • 2022-08-11
    • 2013-01-24
    • 2016-06-15
    • 2019-12-21
    • 1970-01-01
    相关资源
    最近更新 更多