为什么Scala原语在Java反射中不显示为类型参数?

时间:2013-12-23 18:55:49

标签: scala generics reflection

给出以下案例类:

case class Foo(
    bar: Int,
    baz: Boolean,
    qux: Option[Int],
    quux: Option[Boolean],
    quuux: Option[Integer]
)

我希望如下:

for (f <- classOf[Foo].getDeclaredFields) {
    println(f.getGenericType)
}

产生类似的东西:

int
boolean
scala.Option<int>
scala.Option<boolean>
scala.Option<java.lang.Integer>

但相反,它会产生:

int
boolean
scala.Option<java.lang.Object>
scala.Option<java.lang.Object>
scala.Option<java.lang.Integer>

为什么原语会从泛型中删除,而不是被视为java.lang.Integer.TYPEjava.lang.Boolean.TYPE,就像普通字段一样?

有没有办法从classOf[Foo]中检索原始类型参数?

1 个答案:

答案 0 :(得分:9)

Scala认为基元的通用参数是scala.<Primitive>,例如scala.Int。它不会将类型存储在Java类文件中,尽管可以说它可以。 (或者不是;取决于是否需要区分Intjava.lang.Integer;框内形式是java.lang.Integer,即使编译器做得好你也相信它是Int。)

无论如何,Scala有自己的反射功能,但是在2.10你可以找到Option类型的参数,如下所示:

import scala.reflect.runtime.universe._
typeTag[Foo].tpe.members.collect{
  case m: MethodSymbol if m.isCaseAccessor => m 
}.foreach(m => println(m.name + " " + m.typeSignature))

你会得到像

这样的东西
quuux => scala.Option[java.lang.Integer]
quux => scala.Option[scala.Boolean]
qux => scala.Option[scala.Int]
baz => scala.Boolean
bar => scala.Int