惰性字段的序列化是如何工作的?

How does serialization of lazy fields work?

当出于某些原因需要推迟对值的评估时,我知道惰性字段的好处。我想知道惰性字段在序列化方面的行为是什么。

考虑以下 class。

class MyClass {
  lazy val myLazyVal = {...}
  ...
}

问题:

答案

  1. 是的,如果字段已经初始化,如果没有,您可以将其视为一种方法。值未计算 -> 未序列化,但在反序列化后可用。
  2. 如果你没有接触字段,它几乎被序列化,因为它是一个简单的'def'方法,你不需要它的类型本身是可序列化的,它会在反序列化后重新计算
  3. 没有
  4. 您可以在我的代码示例中的 lazy 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

}