Scala反射 - 除非导入Universe,否则MethodSymbol擦除警告._

时间:2015-06-12 11:40:12

标签: scala reflection

我有一个带有泛型类型参数的类,我想获得对泛型类型的构造函数的引用。

如果我导入整个scala.reflect.runtime.universe._而不是导入别名(例如“ru”),这只能在没有删除警告的情况下工作。

我不清楚原因是什么。我怀疑隐含必须从宇宙进入范围,但是没有通过IntelliJ的隐式工具找到任何相关的东西。

任何人都可以告诉我为什么会这样,如果是隐含的,哪一个?

此编译没有警告:

import scala.reflect.runtime.universe._

class CaseClassesExample[T :TypeTag] {

  def doWork: Unit = {
    val tpe = weakTypeTag[T].tpe

    val ctor = tpe.decls.collectFirst {
      case m: MethodSymbol if m.isPrimaryConstructor => m
    }
  }
}

这会编译MethodSymbol的擦除警告:

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

class CaseClassesExample[T : ru.TypeTag] {

  def doWork: Unit = {
    val tpe = ru.weakTypeTag[T].tpe

    val ctor = tpe.decls.collectFirst {
      case m: ru.MethodSymbol if m.isPrimaryConstructor => m
    }
  }
}

警告:

[warn] abstract type pattern reflect.runtime.universe.MethodSymbol is unchecked since it is eliminated by erasure
[warn]       case m: ru.MethodSymbol => m.isConstructor && m.isPrimaryConstructor  
[warn]                  ^

拆分导入:

为了缩小范围,我按如下方式拆分导入 - 有趣的是,IntelliJ声明第二次导入未使用,但删除它会带回警告:

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

class CaseClassesExample[T : ru.TypeTag] {

  def doWork: Unit = {
    val tpe = ru.weakTypeTag[T].tpe

    import scala.reflect.runtime.universe._
    //IntelliJ highlights above import as unused - but removing it brings warning back

    val ctor = tpe.decls.collectFirst {
      case m: ru.MethodSymbol if m.isPrimaryConstructor => m
    }
  }
}

1 个答案:

答案 0 :(得分:1)

原因很简单。 Universe有一个名为MethodSymbolTag的隐式方法(从Symbols特征中混入)定义如下:

implicit val MethodSymbolTag: ClassTag[Universe.MethodSymbol]

范围中存在ClassTag[Universe.MethodSymbol]允许编译器进行擦除。

您可以通过在第二个代码段中添加此导入来验证这一点:

import ru.MethodSymbolTag