2016-11-28 62 views
1

如果我有值:获取类盒装型

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],Class[java.lang.Float]Class[Float]等?

我的意思是这样的功能:

def boxedClass[T]: Class[AnyRef] = ... 
+0

很明显,你不打算使用.asInstanceOf生产?这是不安全的。你尝试使用模式匹配吗? – Pavel

+0

@Pavel我没有在生产中使用这些代码。我只是问问。我不知道模式匹配在这里可以起到什么作用。如果您有任何想法,请提供您的答案。 – mixel

+0

有'Int.box',但我不确定你想要实现什么。 – rethab

回答

3

这似乎在斯卡拉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那就是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扩展为AnyRef

+0

谢谢!我试图玩'Predef'暗示,但我错过了'Boxed.apply'部分。 – mixel