2

外部に保存したいコレクションのインスタンスがあり、元のコレクション タイプに復元します。例えば

class Foo {
  var x : List[Int]
}

val f = new Foo
f.x = List(1, 2, 3)

f を「シリアル化」し、反射的に新しい Foo、f2 を作成し、f2.x に正しい結果を入力したいと考えています。

を実行することで新しい Foo を作成できますがclassOf[Foo].newInstance、正しいコレクション タイプを作成してデータを入力するにはどうすればよいでしょうか。

ここで多くの仮定を立てていることに注意してください。注目すべきは、1) fx の型を知っており、その型をシリアル化することさえできるということです。2) x の内容を、値を保持するものにシリアル化しています。 ) 「標準」のシリアライゼーションは使いたくない

元のコレクションで利用可能なビルダーを使用しようとしましたが、それがどのように機能するのかよくわかりません。

ありがとう、

デイブ

4

1 に答える 1

1

あなたが解決しようとしている問題、例えば、標準的なオブジェクトのシリアル化を使用したくない理由などについて、より良いアイデアがあれば、ここで支援しやすくなります。

とはいえ、本当に Scala コレクション クラスのリフレクションを行いたい場合は、現在 Scala がそのクラスとオブジェクトをどのようにコンパイルしているかについて、おそらくいくつか知っておく必要があります。

  • (List クラスではなく) List オブジェクトのクラスが必要な場合、名前はscala.collection.immutable.List$- 最後のドル記号に注意してください。

  • シングルトン List オブジェクト インスタンスが必要な場合は、 field として格納されますMODULE$

  • ほとんどの scala コレクション コンパニオン オブジェクトは、 ( ) メソッドnewBuilderを持つオブジェクトを作成するメソッドと、新しいコレクションを作成できるメソッドを提供します。+=$plus$eqresult

したがって、次のようなことができます。

scala> def buildByReflection[T](collectionClassName: String, items: Array[T]) = {
     |   val companionClass = Class.forName(collectionClassName + "$")
     |   val companion = companionClass.getField("MODULE$").get(null)
     |   val newBuilder = companionClass.getMethod("newBuilder")
     |   val builder = newBuilder.invoke(companion)
     |   val plusEq = builder.getClass.getMethod("$plus$eq", classOf[Object])
     |   for (item <- items) {
     |     plusEq.invoke(builder, item.asInstanceOf[AnyRef])
     |   }
     |   builder.getClass.getMethod("result").invoke(builder)
     | }
buildByReflection: [T](collectionClassName: String,items: Array[T])java.lang.Object

scala> buildByReflection("scala.collection.immutable.List", Array(1, 2, 3))
res0: java.lang.Object = List(1, 2, 3)
于 2010-12-01T18:11:26.717 に答える