通过反射获取通用值类参数类型

时间:2016-12-02 12:17:19

标签: scala reflection

我希望获得通用值类参数的真实Type。我试过了:

import scala.reflect.runtime.universe._

case class Test[T](value: T) extends AnyVal

object Main extends App {
  val tag = implicitly[TypeTag[Test[String]]]
  val constructor = tag.tpe.members.collect {
    case m: MethodSymbol if m.isPrimaryConstructor => m
  }.headOption
  val constructorParams = constructor.map(_.paramLists.flatten).collect {
    case param :: Nil => param
  }
  constructorParams.map(_.typeSignature).foreach(println)
}

但它打印出来:

  

Ť

我知道我可以通过以下方式获取类型参数:

tag.tpe.typeArgs.foreach(println)

输出:

  

字符串

Test类可以这样定义:

case class Test[T](value: List[T]) extends AnyVal

因此类型参数和参数类型的类型不同。

我该怎么做?

1 个答案:

答案 0 :(得分:1)

编译器中有一个名为"的操作,如"它返回与特定所有者类型相关的成员类型。

以下是REPL会话中的一个示例:

Welcome to Scala 2.12.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_102).
Type in expressions for evaluation. Or try :help.

scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._

scala> case class Test[T](value: List[T]) extends AnyVal
defined class Test

scala> val tp = typeOf[Test[String]]
tp: reflect.runtime.universe.Type = Test[String]

scala> val cls = tp.typeSymbol
cls: reflect.runtime.universe.Symbol = class Test

scala> val constructor = tp.members.collect({case m: MethodSymbol if m.isPrimaryConstructor => m}).head
constructor: reflect.runtime.universe.MethodSymbol = constructor Test

scala> constructor.info.asSeenFrom(tp, cls).paramLists.head.head.info
res0: reflect.runtime.universe.Type = scala.List[String]

scala> // alternatively

scala> constructor.infoIn(tp).paramLists.head.head.info
res1: reflect.runtime.universe.Type = scala.List[String]