为什么Scala原语不会在Java反射中显示为类型参数? [英] Why don't Scala primitives show up as type parameters in Java reflection?

查看:171
本文介绍了为什么Scala原语不会在Java反射中显示为类型参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定以下案例类:

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

 println(f.getGenericType)
}
$ c


$ b

产生类似于:

  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.TYPE java.lang.Boolean.TYPE ,看起来和普通字段一样吗?



是否有任何方法从 classOf [Foo]

scala。< Primitive>
eg scala.Int 。它不会将类型存储在Java类文件中,尽管可以这么说。 (或不是;取决于是否需要区分 Int java.lang.Integer ;在即使编译器做得很好,让你相信它是 Int ,那么这个盒装表单就是 java.lang.Integer )。

无论如何,Scala有其自己的反射功能,它们在不断变化中,但在2.10中,您可以找到 Option的参数 code>类型如下所示:

  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


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]?

解决方案

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

这篇关于为什么Scala原语不会在Java反射中显示为类型参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆