Stefan K.
Stefan K.

Reputation: 7851

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.getClass //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

Upvotes: 5

Views: 5659

Answers (3)

Régis Jean-Gilles
Régis Jean-Gilles

Reputation: 32739

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

Upvotes: 3

retronym
retronym

Reputation: 55028

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

Upvotes: 8

Arjan Blokzijl
Arjan Blokzijl

Reputation: 6888

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

Upvotes: 3

Related Questions