@transient lazy val field serialization
10,978
There's a couple of tickets on this in Scala's Trac:
I'd advise you to test against a trunk build of 2.9, as it may already be fixed.
Related videos on Youtube
Author by
hydrocul
Updated on April 29, 2022Comments
-
hydrocul about 2 years
I have a problem on Scala. I serialize an instance of class with
@transient lazy val
field. And then I deserialize it, the field is assignednull
. I expect the lazy evaluation after deserialization. What should I do?Following is a sample code.
object Test { def main(args: Array[String]){ //---------------- // ClassA - with @transient //---------------- val objA1 = ClassA("world"); println(objA1); // This works as expected as follows: // "Good morning." // "Hello, world" saveObject("testA.dat", objA1); val objA2 = loadObject("testA.dat").asInstanceOf[ClassA]; println(objA2); // I expect this will work as follows: // "Good morning." // "Hello, world" // but actually it works as follows: // "null" //---------------- // ClassB - without @transient // this works as expected //---------------- val objB1 = ClassB("world"); println(objB1); // This works as expected as follows: // "Good morning." // "Hello, world" saveObject("testB.dat", objB1); val objB2 = loadObject("testB.dat").asInstanceOf[ClassB]; println(objB2); // This works as expected as follows: // "Hello, world" } case class ClassA(name: String){ @transient private lazy val msg = { println("Good morning."); "Hello, " + name; } override def toString = msg; } case class ClassB(name: String){ private lazy val msg = { println("Good morning."); "Hello, " + name; } override def toString = msg; } import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; def saveObject(fname: String, obj: AnyRef){ val fop = new FileOutputStream(fname); val oop = new ObjectOutputStream(fop); try { oop.writeObject(obj); } finally { oop.close(); } } def loadObject(fname: String): AnyRef = { val fip = new FileInputStream(fname); val oip = new ObjectInputStream(fip); try { oip.readObject(); } finally { oip.close(); } } }
-
hydrocul over 13 yearsThank you very much. I'll try 2.9.
-
tksfz over 9 yearsJust an update that this works fine in Scala 2.10.4. However, I notice it's still broken if the initializer relies on a by-name argument. For example, make ClassA.name be
=> String
and it won't work. (You'll also need to make it a non-case class that extends Serializable, and make name a val.)