Object Serialization in Java

Java offers ObjectInputStream and ObjectOutputStream, which, when chained to FileInputStream and FileOutputStream, can be used by programs to read and write objects. The process of writing an object to somewhere is called object serialization, and the process of reading a serialized object back into the program is called deserialization.

The goal here is to save the state of an object. Even without serialization, you could use the I/O classes to save the object state and restore it at a later time. However, all programmers would need to do it in their own way, and the process would be prone to errors. Serialization standardizes and automates the process of saving the state of an object, and hence makes it robust. Simply put, through serialization, Java allows you to say: save this object along with its instance variables, except this variable and that variable. For example, if you declare a variable transient, it will not be saved in serialization.

To make the objects of a class serializable, the class must implement the interface Serializable:

    class MySerialClass implements Serializable {
         // body of the class
    }

The Serializable interface is an empty interface (i.e. no methods are declared inside it) and is used to just tag a class for possible serialization. To make your class serializable in this way is the necessary condition to enable the objects of the class to be serialized. Obviously, you need to do more work to actually serialize the objects.


Objet Serialization

To serialize an object to a file, you use the ObjectOutputStream to write it to a low-level stream, which in turn will write it to the file. For example, consider the following code fragment:

   FileOutputStream out = new FileOutputStream("objectStore.ser");
   ObjectOutputStream os = new ObjectOutputStream(out);
   os.writeObject("serialOut");
   os.writeObject(new MySerialClass());
   os.writeObject("End of storage!");
   os.flush();

Note that ObjectOutputStream must be chained to another stream because it cannot write directly to a device (file or socket). In the preceding example, we chain an ObjectOutputStream to a FileOutputStream, which can write it to a file. Also note that a string and two objects are written to the stream by invoking the writeObject(…) method. If you pass in an object that is not serializable, the writeObject method will throw a NotSerializableException.

Only the data of the object (along with the class name) is saved, and not the class definition. The static and transient variables are not saved. To be specific, the following are saved in serialization:

• The values of the instance variables of the serialized object.
• The class description of the object, which includes the class name, the serial version unique ID, a set of flags describing the serialization method, and a description of the data fields.
• All the objects that a serialized object refers to through object reference variables. That means those objects must be serializable; otherwise, you will get a compiler error.

The objects can be read back (de-serialized) in the same order in which they were stored.

Objet Deserialization

Once you’ve written objects and primitive data types to a stream, you’ll likely want to read them again and reconstruct the objects. This is also straightforward. Here is a code fragment that reads in the String and the Date objects that were written to the file named objectStore.ser in the previous example:
    
       FileInputStream in = new FileInputStream("objectStore.ser");
       ObjectInputStream is = new ObjectInputStream(in);
       String note = (String)is.readObject();
       MySerialClass serialIn1 = (MyClassSerial)is.readObject();
       MySerialClass serialIn2 = (MyClassSerial)is.readObject();

Just like ObjectOutputStream, ObjectInputStream must be chained to another stream because it cannot read directly from the device (file or socket). In the preceding example, our code chains an ObjectInputStream to a FileInputStream, and uses the ObjectInputStream’s readObject() method to read the two objects and a string that we stored earlier in a file. Note that the objects must be read in the same order in which they were written. Further note that the object returned by the readObject() method is cast to a proper type before assigning it to a declared object reference.

Key points about Object Serialization 

Note the following points about serialization:

• If a class is serializable, then all the subclasses of this superclass are implicitly serializable even if they don’t explicitly implement the Serializable interface.
• If you want to serialize an array (or some other collection), each of its elements must be serializable.
• Static variables are not saved as part of serialization. Recall that the purpose of serialization is to save the state of an object, and a static variable belongs to the class and not to an object of the class.


Reference(s): SCJP Exam for J2SE 5 

4 comments: