我有一个集合的实例,我想在外部存储,然后还原回原始集合类型。例如
class Foo {
var x : List[Int]
}
val f = new Foo
f.x = List(1, 2, 3)
我“序列化”了f,我想反思地创建一个新的Foo,f2,并用正确的结果填充f2.x.
我可以通过classOf[Foo].newInstance
创建新的Foo,但是如何创建正确的集合类型并填充它呢?
注意,我在这里做了很多假设,值得注意的是: 1)我知道f.x的类型,我甚至可以序列化它的类型 2)我将x的内容序列化为保留值的东西 3)我不想使用任何“标准”序列化
我已经尝试使用原始集合中可用的构建器,但我不太明白它是如何工作的,以便将它拉下来。
谢谢,
戴夫
答案 0 :(得分:1)
如果我们更好地了解您要解决的问题,例如,这将更容易帮助。为什么你不想使用标准对象序列化。
那就是说,如果你真的想对Scala集合类进行反思,你可能需要了解一些关于Scala当前如何编译其类和对象的事情:
如果您想要List对象的类(不是List类),则名称为scala.collection.immutable.List$
- 请注意最终的美元符号。
如果您需要单例列表对象实例,则将其存储为字段MODULE$
。
大多数scala集合伴随对象提供newBuilder
方法,该方法创建一个具有+=
($plus$eq
)方法和result
方法的对象,创建一个新的集合。
所以你可以这样做:
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)