【发布时间】:2016-12-25 17:47:02
【问题描述】:
为什么我可以序列化这个:
// Serialize: OK
case class ClassWithType2[T:TypeTag](x:T) {
val tpe:java.lang.reflect.Type = Util.toJavaClass[T]
}
...但不是这个
class TypeAware[T:TypeTag]() {
val tpe:java.lang.reflect.Type = Util.toJavaClass[T]
}
// Serialize: FAIL.
// No valid constructor for ClassWithType1
// in: java.io.ObjectStreamClass.checkDeserialize
case class ClassWithType1[T:TypeTag](x:T) extends TypeAware[T]
两者似乎具有相同的构造函数类型原型:
[T:TypeTag](x:T)
并且都扩展了 scala.Serializable 和 java.io.Serializable
val s1:Serializable = ClassWithType1(x=123)
val s2:Serializable = ClassWithType2(x=123)
val s3:java.io.Serializable = ClassWithType1(x=123)
val s4:java.io.Serializable = ClassWithType2(x=123)
有一种方法可以实现 TypeAware 子类:
- 避免必须在每个子类中声明 tpe(如 ClassWithType2 所做的那样)?
- 允许序列化对象
这是测试工具
class TypesTest {
@Test
def serializeTypeTest(): Unit = {
val obj2:Object = ClassWithType2(x=123)
Util.copyBySerialization(obj2) // Success!
val obj1:Object = ClassWithType1(x=123)
Util.copyBySerialization(obj1) // Fail
}
}
object Util {
def toJavaClass[T:TypeTag]: Class[_] = {
val tpe = typeOf[T]
runtimeMirror(tpe.getClass.getClassLoader).runtimeClass(tpe.typeSymbol.asClass)
}
def copyBySerialization[T](obj: T): T = deserialize(serialize(obj))
def serialize[T](obj: T): Array[Byte] = {
val byteOut = new ByteArrayOutputStream()
val objOut = new ObjectOutputStream(byteOut)
objOut.writeObject(obj)
objOut.close()
byteOut.close()
byteOut.toByteArray
}
def deserialize[T](bytes: Array[Byte]): T = {
val byteIn = new ByteArrayInputStream(bytes)
val objIn = new ObjectInputStream(byteIn)
val obj = objIn.readObject().asInstanceOf[T]
byteIn.close()
objIn.close()
obj
}
}
【问题讨论】:
-
TypeAware 没有扩展 java.io.Serializable。
-
为什么需要它?我要求序列化 ClassWithType1,它声称是可序列化的。注意。序列化失败是因为找不到 ClassWithType1 的构造函数,而不是因为无法序列化 TypeAware 或其成员(序列化 java.reflect.Type 工作正常)。
-
每隔几年,我都会尝试刷新我对 Java 序列化的记忆,但我不认为今天是这一天。但是请看我的回答; ctor 不是无效的。
标签: scala generics serialization scala-generics