Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@transient lazy val field serialization

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 assigned null. 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();
    }
  }

}
like image 972
hydrocul Avatar asked Jan 23 '11 07:01

hydrocul


People also ask

What is transient lazy Val in Scala?

In Scala lazy val denotes a field that will only be calculated once it is accessed for the first time and is then stored for future reference. With @transient on the other hand one can denote a field that shall not be serialized.

Why are transient variables not serialized?

In case you define any data member as transient, it will not be serialized. This is because every field marked as transient will not be serialized. You can use this transient keyword to indicate the Java virtual machine (JVM) that the transient variable is not part of the persistent state of an object.

How do you make a field transient in Java?

transient is a variables modifier used in serialization. At the time of serialization, if we don't want to save value of a particular variable in a file, then we use transient keyword. When JVM comes across transient keyword, it ignores original value of the variable and save default value of that variable data type.

What is serializable in Scala?

Serializing an object means taking the data stored in an object and converting it to bytes (or a string). Suppose you want to write the data in an object to a JSON file. JSON files store strings. JSON has no understanding about the JVM or Scala objects.


1 Answers

There's a couple of tickets on this in Scala's Trac:

  • 1573
  • 1574

I'd advise you to test against a trunk build of 2.9, as it may already be fixed.

like image 153
Kevin Wright Avatar answered Sep 22 '22 07:09

Kevin Wright