如果我有价值:
val i: Int = 1
我可以上课:
> i.getClass
res1: Class[Int] = int
和盒装价值类:
> i.asInstanceOf[AnyRef].getClass
res2: Class[_ <: AnyRef] = class java.lang.Integer
问题是如何从没有值的任何基本类型的类中获取盒装类型的类,例如它应该为Class[java.lang.Integer]
返回Class[Int]
,为{{1}返回Class[java.lang.Float]
等等?
我的意思是这种功能:
Class[Float]
答案 0 :(得分:4)
这似乎适用于scala 2.11.x和2.12.x,这有点令我惊讶。
scala> import scala.reflect.ClassTag
import scala.reflect.ClassTag
scala> class Boxed[T <: AnyVal] { def apply[R <: AnyRef]()(implicit conv: T => R, tag: ClassTag[R]) = tag.runtimeClass }
defined class Boxed
scala> def boxedClass[T <: AnyVal] = new Boxed[T]
boxedClass: [T <: AnyVal]=> Boxed[T]
scala> boxedClass[Int]()
res5: Class[_] = class java.lang.Integer
scala> boxedClass[Double]()
res6: Class[_] = class java.lang.Double
它的工作原理是将T
修改为您希望装箱类的类型,然后查找T
到类型R
的转换,该类型是{{1}的子类型}}。然后你拿走AnyRef
,你就拥有了你正在寻找的课程。
更高级的解决方案是:
ClassTag[R]
用法:
sealed trait BoxedClass[T <: AnyVal] {
type R <: AnyRef
def clazz: Class[R]
}
object BoxedClass {
import scala.reflect.ClassTag
implicit def mkBoxedClass[T <: AnyVal, R0 <: AnyRef](
implicit
conv: T => R0,
tag: ClassTag[R0]) =
new BoxedClass[T] {
type R=R0
val clazz = tag.runtimeClass.asInstanceOf[Class[R]]
}
}
def boxedClass[T <: AnyVal](implicit b: BoxedClass[T]): Class[b.R] = b.clazz
另请注意,如果您将scala> boxedClass[Int]
res0: Class[Integer] = class java.lang.Integer
scala> boxedClass[Long]
res1: Class[Long] = class java.lang.Long
中的任何其他隐式转化定义或导入到扩展Int
的类型,则此功能将不再有效。