【发布时间】:2014-07-18 04:09:21
【问题描述】:
这是对以下问题的跟进,涉及序列化:How best to keep a cached list of member fields, one each for a family of case classes in Scala
我正在尝试以同样的方式普遍支持反序列化。一种直接的尝试如下:
abstract class Serializer[T](implicit ctag: ClassTag[T]) {
private val fields = ctag.runtimeClass.getDeclaredFields.toList
fields foreach { _.setAccessible(true) }
implicit class AddSerializeMethod(obj: T) {
def serialize = fields.map(f => (f.getName, f.get(obj)))
}
def deserialize(data: List[(String, Any)]): T = {
val m = data toMap
val r: T = ctag.runtimeClass.newInstance // ???
fields.foreach { case f => f.set(r, m(f.getName)) }
r;
}
}
代码有几个问题:
-
val r: T = ...的行存在编译错误,因为编译器认为不能保证它具有正确的类型。 (我通常不确定如何以类型安全的方式创建泛型类的新实例——不确定为什么这不安全,因为 Serializer 的实例是使用编译器检查其类型的类标记创建的) . - 我正在创建的对象应该是不可变的案例类对象,如果以通常的方式创建,则可以保证它们是完全构造的。但是,由于我在反序列化方法中对这些对象的实例字段进行了变异,如果将这些对象发布到其他线程,我如何确保它们不会被视为部分构造(由于缓存和指令重新排序)?
【问题讨论】:
-
这样做并不安全,但对于#1,您可以通过以下方式解决此问题:
val r: T = ctag.runtimeClass.newInstance.asInstanceOf[T]。不过,我想不出这样不安全的情况。
标签: scala reflection