HowTo get the class of _ :Any
I've wrapped a Message and would like to log which message I've wrapped.
val any :Any = msg.wrappedMsg
var result :Class[_] = null
The only solution I could find is matching everything:
result = any match {
case x:AnyRef => x.getClass
case _:Double => classOf[Double]
case _:Float => classOf[Float]
case _:Long => classOf[Long]
case _:Int => classOf[Int]
case _:Short => classOf[Short]
case _:Byte => classOf[Byte]
case _:Unit => classOf[Unit]
case _:Boolean=> classOf[Boolean]
case _:Char => classOf[Char]
}
I wonder if there's a better solution? The following 2 approaches do not work :(
result = any.getClas开发者_如何学Cs //error
// type mismatch; found : Any required: ?{val getClass: ?}
// Note: Any is not implicitly converted to AnyRef.
// You can safely pattern match x: AnyRef or cast x.asInstanceOf[AnyRef] to do so.
result = any match {
case x:AnyRef => x.getClass
case x:AnyVal => /*voodoo to get class*/ null // error
}
//type AnyVal cannot be used in a type pattern or isInstanceOf
You can safely call .asInstanceOf[AnyRef]
on any Scala value, which will box primitives:
scala> val as = Seq("a", 1, 1.5, (), false)
as: Seq[Any] = List(, 1, 1.5, (), false)
scala> as map (_.asInstanceOf[AnyRef])
res4: Seq[AnyRef] = List(a, 1, 1.5, (), false)
From there, you can call getClass
.
scala> as map (_.asInstanceOf[AnyRef].getClass)
res5: Seq[java.lang.Class[_]] = List(class java.lang.String, class java.lang.Int
eger, class java.lang.Double, class scala.runtime.BoxedUnit, class java.lang.Boo
lean)
Tested with 2.8.0.RC6, I don't know it this worked in 2.7.7.
Definitely new in 2.8 are the companion objects for the classes derived from AnyVal. They contain handy box
and unbox
methods:
scala> Int.box(1)
res6: java.lang.Integer = 1
scala> Int.unbox(res6)
res7: Int = 1
Won't casting just do the trick, as suggested in the error message?
scala> val d:Double = 0.0
d: Double = 0.0
scala> d.asInstanceOf[AnyRef].getClass
res0: java.lang.Class[_] = class java.lang.Double
As of scala 2.10.0, getClass
is available on Any
(and not just on AnyRef
), so you don't need to do any contorsion anymore and can just do any.getClass
.
Note though that you still must be prepared to handlet the dual relation between primitive types and their boxed version.
By example getClass
on an integer value will return either java.lang.Integer.TYPE
(the class of the primitive Int
type) or classOf[java.lang.Integer]
depending on the static type of the value:
scala> 123.getClass
res1: Class[Int] = int
scala> val x : Int = 123
x: Int = 123
scala> x.getClass
res2: Class[Int] = int
scala> val x: AnyVal = 123
x: AnyVal = 123
scala> x.getClass
res3: Class[_] = class java.lang.Integer
scala> val x: Any = 123
x: Any = 123
scala> x.getClass
res4: Class[_] = class java.lang.Integer
精彩评论