当由于某些原因需要推迟评估值时,我知道惰性字段的好处。我想知道惰性字段在序列化方面的行为是什么。
考虑下面的类。
class MyClass {
lazy val myLazyVal = {...}
...
}
问题:
- 如果 MyClass 的实例被序列化,惰性字段也会被序列化吗?
- 如果在序列化之前字段已被访问或未访问,序列化的行为是否会改变?我的意思是,如果我不导致该字段的评估,它是否被视为null?
- 序列化机制是否会引发惰性字段的隐式求值?
- 有没有一种简单的方法可以避免变量的序列化并在反序列化后延迟重新计算一次值?这应该独立于该领域的评估而发生。
最佳答案
答案
- 是的,如果字段已经初始化,如果没有,你可以将它作为一个方法。值未计算 -> 未序列化,但在反序列化后可用。
- 如果你没有触及字段,它几乎会被序列化,因为它是一个简单的“def”方法,你不需要它的类型本身可序列化,它会在反序列化后重新计算
- 没有
- 您可以在我的代码示例中的惰性 val 定义之前添加 @transient,据我所知,它将完全按照您的要求进行操作
证明代码
object LazySerializationTest extends App {
def serialize(obj: Any): Array[Byte] = {
val bytes = new ByteArrayOutputStream()
val out = new ObjectOutputStream(bytes)
out.writeObject(obj)
out.close()
bytes.toByteArray
}
def deSerialise(bytes: Array[Byte]): MyClass = {
new ObjectInputStream(new ByteArrayInputStream(bytes)).
readObject().asInstanceOf[MyClass]
}
def test(obj: MyClass): Unit = {
val bytes = serialize(obj)
val fromBytes = deSerialise(bytes)
println(s"Original cnt = ${obj.x.cnt}")
println(s"De Serialized cnt = ${fromBytes.x.cnt}")
}
object X {
val cnt = new AtomicInteger()
}
class X {
// Not Serializable
val cnt = X.cnt.incrementAndGet
println(s"Create instance of X #$cnt")
}
class MyClass extends Serializable {
lazy val x = new X
}
// Not initialized
val mc1 = new MyClass
test(mc1)
// Force lazy evaluation
val mc2 = new MyClass
mc2.x
test(mc2) // Failed with NotSerializableException
}
关于scala - 惰性字段的序列化如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27882307/