Convert Scala Any to Java Object

Torben picture Torben · May 27, 2014 · Viewed 19.1k times · Source

I've a problem using Java Reflection from Scala. My Code:

case class MyClass(id: String, value: Double)     

def create(values: Map[String, Any]): MyClass = {
   val constructor = classOf[MyClass].getConstructors.head
   val arguments = classOf[MyClass].getDeclaredFields().map( f => values(f.getName) )
   constructor.newInstance(arguments: _*).asInstanceOf[MyClass]
} 

create(Map("id" -> "CE0D23A", "value" -> 828.32))

My problem is, that I need to pass a Map[String, Any], because one of the values is a Double, but newInstance needs Object, not Any.

I tried the same with scalas universe:

case class MyClass(id: String, value: Double)     

def create(values: Map[String, Any]): MyClass = {
   val m = universe.runtimeMirror(getClass.getClassLoader)
   val myClass = universe.typeOf[MyClass].typeSymbol.asClass
   val cm = m.reflectClass(myClass)
   val ctro = universe.typeOf[MyClass].declaration(universe.nme.CONSTRUCTOR).asMethod
   val ctorm = cm.reflectConstructor(ctro)
   ctorm(values: _*).asInstanceOf[MyClass]
} 

create(Map("id" -> "CE0D23A", "value" -> 828.32))

Problem here is, that I only introduced MyClass for the example. Later it should be a generic function like def create(values: Map[String, Any]): T. But then I got the following exception: "No TypeTag available for T"

Is there any way to transform these values?

Thank you

Answer

Dan Getz picture Dan Getz · May 27, 2014

java.lang.Object is equivalent to AnyRef in Scala, not Any. The idea is, Scala Double (roughly equivalent to Java double) is an Any, but not an AnyRef. java.lang.Double is an AnyRef, thus also an Any.

You can simply cast an Any to AnyRef, which will perform the needed conversion to turn a Scala Double into a java.lang.Double:

scala> val x = 3.5
x: Double = 3.5

scala> x.getClass
res0: Class[Double] = double

scala> val y = x.asInstanceOf[AnyRef]
y: AnyRef = 3.5

scala> y.getClass
res1: Class[_ <: AnyRef] = class java.lang.Double