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
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