从原始类的类中获取盒装类型

时间:2016-11-28 10:23:15

标签: scala

如果我有价值:

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]

1 个答案:

答案 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的类型,则此功能将不再有效。