【问题标题】:Scala - No TypeTag Available Exception when using case class to try to get TypeTag?Scala - 使用案例类尝试获取 TypeTag 时没有可用的 TypeTag 异常?
【发布时间】:2013-06-04 00:34:14
【问题描述】:

我正在查看 scala reflect API,但遇到了很多异常。

文档参考: http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html

如何从泛型中获取类型标签?

  def getChildSettings[T: ru.TypeTag](path: String, settingsParameterObject: T) = {

    import scala.reflect.runtime.{ currentMirror => m }

    val m = ru.runtimeMirror(getClass.getClassLoader)
    val classC = ru.typeOf[T].typeSymbol.asClass
}

我得到一个例外:

No TypeTag available for ParameterObject.type

即使是一个非常简单的示例似乎也不起作用(编辑是的,它在 repl 中起作用)

import scala.reflect.runtime.universe._
import scala.reflect.runtime.currentMirror
import scala.reflect.runtime.{universe => ru}

def getTypeTag[T: ru.TypeTag](obj: T) = ru.typeTag[T]

case class ParameterObject(stringType: String, optionType: Option[String])

getTypeTag(ParameterObject)

我猜这与我如何调用该方法有关。

【问题讨论】:

  • 嗯,只需将您的简单示例粘贴到 REPL 中(并删除 settings.)在 2.10.1 上对我有用。你会在你的类路径上缺少 scala-reflect 吗?
  • 残酷!你是对的,它在 repl 中确实有效。我想通了 - 案例类不能嵌套!我在测试用例中定义了案例类,这就是导致问题的原因。

标签: scala reflection types


【解决方案1】:

在编译时需要TypeTag,因为这是解决擦除问题的方法:

import scala.reflect.runtime.{currentMirror => m, universe => ru}

def getChildSettings[T: TypeTag](path: String, settingsParameterObject: T) = {
  val tpe    = ru.typeOf[T]
  // val classC = tpe.typeSymbol.asClass
  val ctor   = tpe.declaration(ru.nme.CONSTRUCTOR).asMethod
  ...
}

Scala Documentation Overview for Reflection 给出了获取和调用构造函数的示例。

【讨论】:

  • 啊,好吧。我知道了。实际上我必须去 [T: ru.TypeTag] - 谢谢伙计 - 我看不到我错过了什么。
  • 我认为这就是我调用方法的方式。
  • 我更新了问题 - 如果这有助于澄清我的问题所在,请告诉我。
  • 感谢您的帮助 - 我想通了 - 案例类不能嵌套 - 它们必须是顶级的,否则会引发异常。
【解决方案2】:

我终于找到了问题所在。 案例类必须定义在顶层——它们不能嵌套。 这样的事情会失败。

class Foo {
  describe("getSettings") {
    case class ParameterObject(foo: String)
    settings.getTypeTag(path, ParameterObject)
  }
}

class Clazzy {
      def getTypeTag[T: TypeTag](obj: T) = ru.typeTag[T]
}

【讨论】:

  • 阅读此内容的每个人,另请参阅雅罗斯拉夫的回答。您可以要么将所有类移至顶层并继续使用typeOf/TypeTag将它们保留在原处并改用weakTypeOf/WeakTypeTag . (如果两个函数都起作用,它们会产生相同的输出。)
  • 这是否意味着我们无法编写如您原始帖子中所示的简单 scala 脚本并使其运行?
【解决方案3】:

如果你需要嵌套类的类型标签,你可以使用 Wea​​kTypeTag。我不知道为什么,但是that's intentionally

【讨论】:

    【解决方案4】:

    请在运行主类之前声明案例类

    例子

    case class Person(name: String, age: Long)
    
    def main(args: Array[String]) {
       ...
        val people = sc.textFile("C:\\winutils\\people.txt").map(_.split(",")).map(p => Person(p(0), p(1).trim.toInt)).toDF()
    

    【讨论】:

      【解决方案5】:

      将此代码添加到您的 pom.xml 中

      <dependency>
          <groupId>org.scala-lang</groupId>
          <artifactId>scala-reflect</artifactId>
          <version>2.12.0-M4</version>
      </dependency>
      

      【讨论】:

      • 非常感谢!线程末尾的这条评论 - 对我有用!
      • 是的,在 Apache Spark 的上下文中也帮助了我。
      • 不推荐。 scala-reflect 是 Scala 编译器的一部分,应该与 Scala 的版本相匹配,否则会引入另一个 scala-library 的依赖关系。
      • 我正在使用导致此错误的不同版本的 scala。
      猜你喜欢
      • 1970-01-01
      • 2017-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-25
      • 1970-01-01
      • 1970-01-01
      • 2020-06-28
      相关资源
      最近更新 更多