Ответ 1
ответы
- Да, если поле уже было инициализировано, если вы не можете направить его как метод. Значение не вычисляется → не сериализовано, но доступно после сериализации.
- Если вы не касались поля, он сериализован почти так же, как и простой метод "def", вам не нужно, чтобы он был сериализуемым, он будет пересчитан после де-сериализации
- нет
- Вы можете добавить @transient до определения ленивого val в моем примере кода, так как я понимаю, что он будет делать именно то, что вы хотите
Код для доказательства
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
}