Преобразование Scala Любой объект Java

У меня проблема с использованием Java Reflection из Scala. Мой код:

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

Моя проблема в том, что мне нужно передать карту [String, Any], потому что одно из значений - это Double, но newInstance требует Object, а не Any.

Я пробовал то же самое со вселенной scalas:

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

Проблема здесь в том, что я только представил MyClass для примера. Позже это должна быть общая функция типа def create(values: Map[String, Any]): T. Но затем я получил следующее исключение: "Нет TypeTag для T"

Есть ли способ преобразовать эти значения?

Спасибо

Ответы

Ответ 1

java.lang.Object эквивалентен AnyRef в Scala, а не Any. Идея заключается в том, что Scala Double (примерно эквивалентно Java Double) является Any, но не AnyRef. java.lang.Double является AnyRef, а также a Any.

Вы можете просто нарисовать Any до AnyRef, который выполнит необходимое преобразование, чтобы включить Scala Double в 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

Ответ 2

Хорошо, я немного опоздал, но здесь идет:

Следующие работы:

constructor.newInstance(arguments.asInstanceOf[Array[AnyRef]]: _*).asInstanceOf[MyClass]

Смотрите также: Преобразование Scala varargs в объект Java... varargs

Совет: я бы очень осторожно использовал отражение. В Scala это плохой стиль. Одним из способов ограничить/инкапсулировать его может быть:

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

object MyClass {

    import scala.util.Try
    def apply(map: Map[String, Any] /* this is asking for trouble */) : Option[MyClass]  =  for {
            id <- maybeT[String](map.get("id"))
            value <- maybeT[Double](map.get("value"))
        } yield MyClass(id, value)

    // a truly global utility?
    @inline def maybeT[T] ( a: Any /*Option[T]*/ ) : Option[T]= Try(a.asInstanceOf[Option[T]]).toOption.flatten //yep ugly as hell

}


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