Search code examples
classscalatypesscala-2.8type-systems

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

Solution

  • 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