Java 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))
_
私の問題は、Map [String、Any]を渡す必要があることです。値の1つがDoubleですが、newInstanceにはAnyではなくObjectが必要です。
私はスカラ宇宙で同じことを試しました:
_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
のような汎用関数になるはずです。しかし、次の例外が発生しました:「Tで使用できるTypeTagはありません」
これらの値を変換する方法はありますか?
ありがとうございました
Java.lang.Object
は、AnyRef
ではなく、ScalaのAny
と同等です。 Scala Double
(Java double
とほぼ同等)はAny
ですが、AnyRef
ではありません。Java.lang.Double
はAnyRef
であるため、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
わかりました。少し遅れましたが、次のとおりです。
次の作品:
constructor.newInstance(arguments.asInstanceOf[Array[AnyRef]]: _*).asInstanceOf[MyClass]
参照: Transforming Scala varargs into Java Object ... varargs
アドバイス:リフレクションの使用には非常に注意が必要です。 Scalaこれは悪いスタイルです。これを制限/カプセル化する1つの方法は次のとおりです。
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))