Why don't Scala primitives show up as type parameters in Java reflection?

半世苍凉 提交于 2020-01-01 08:36:07

问题


Given the following case class:

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

I would expect the following:

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

to produce something like:

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

But instead, it produces:

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

Why do the primitives get erased from the generics, instead of getting treated as java.lang.Integer.TYPE and java.lang.Boolean.TYPE, as appears to happen with the plain fields?

And is there any way to retrieve the primitive type parameters from classOf[Foo]?


回答1:


Scala thinks that the generic parameter for primitives is scala.<Primitive> e.g. scala.Int. It doesn't store the type in the Java class file, though arguably it could. (Or not; depends on whether there needs to be a distinction between Int and java.lang.Integer; under the hood the boxed form is java.lang.Integer, even if the compiler does a good job making you believe it is Int.)

Anyway, Scala has its own reflection capabilities which are in flux, but with 2.10 you can find the arguments of the Option types like so:

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

and you'll get something like

quuux => scala.Option[java.lang.Integer]
quux => scala.Option[scala.Boolean]
qux => scala.Option[scala.Int]
baz => scala.Boolean
bar => scala.Int


来源:https://stackoverflow.com/questions/20749536/why-dont-scala-primitives-show-up-as-type-parameters-in-java-reflection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!