Serialization

Object Serialization in Java is a process used to convert Object into a binary format which can be persisted into disk or sent over network to any other running Java virtual machine; the reverse process of creating object from binary stream is called deserialization in Java.

To make  a class Serializable, your class just needs to implements java.io.Serializable interface and JVM will take care of serializing object in default format. Serializable interface doesn’t have any method and also called Marker Interface in Java. It only gives compiler an indication that use Java Serialization mechanism to serialize this object.

Lets take an simple example.


package mynotes.serializtion;

import java.io.Serializable;

public class Person implements Serializable{

private String name;
 private int age;

public Person() {

}

public Person(String name, int age) {
 this.name = name;
 this.age = age;
 }

public String getName() {
 return name;
 }

public int getAge() {
 return age;
 }

 @Override
 public String toString() {

 return "Name::"+this.name+" Age::"+this.age;
 }
}


package mynotes.serializtion;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class SerializationBasic {

 public void writeObjects(){
 System.out.println("Writing Objects Begin...");

 Person person1=new Person("Jack",23);
 Person person2=new Person("Jill",25);
 System.out.println(person1);
 System.out.println(person2);
 FileOutputStream fos=null;
 ObjectOutputStream oos=null;

 try {
 fos =new FileOutputStream("storage.dat");
 oos=new ObjectOutputStream(fos);

 oos.writeObject(person1);
 oos.writeObject(person2);

 oos.close();
 fos.close();

 } catch (FileNotFoundException e) {
 // TODO Auto-generated catch block
 e.printStackTrace();
 } catch (IOException e) {
 // TODO Auto-generated catch block
 e.printStackTrace();
 }

 System.out.println("Writing Objects Exit...");

 }

 public void readObjects(){
 System.out.println("Reading Objects Begin...");
 FileInputStream fis=null;
 ObjectInputStream ois=null;

 try {
 fis=new FileInputStream("storage.dat");
 ois=new ObjectInputStream(fis);

 Person person1=(Person) ois.readObject();
 Person person2=(Person) ois.readObject();
 System.out.println(person1);
 System.out.println(person2);

 ois.close();
 fis.close();

 } catch (FileNotFoundException e) {
 // TODO Auto-generated catch block
 e.printStackTrace();
 } catch (IOException e) {
 // TODO Auto-generated catch block
 e.printStackTrace();
 } catch (ClassNotFoundException e) {
 // TODO Auto-generated catch block
 e.printStackTrace();
 }

 System.out.println("Reading Objects Exit...");
 }

 public static void main(String[] args) {

 SerializationBasic aSerializationBasic=new SerializationBasic();
 aSerializationBasic.writeObjects();
 aSerializationBasic.readObjects();
 }

}

Above we have a simple Person class with 2 attributes, and implements Serialzable interface. The second class is out main class with 2 moethods, one writes the object in a binary file (“storage.dat” , note that extension doesn’t matter) and the others read that binary file. Notice that we didn’t gave any file path so the file will be made on your local project itself, hit refresh in the project after you run the program and you can see the file.
Lets see the writeObject method – it makes an object of FileOutputStream which will save the file after the ObjectOutputStream does it work. Notice we simply called writeObject method of the ObjectOutputStream object to save our objects. The readObject method is also pretty self explanatory.
Note: Reading writing differnt objects is fine as long as we remember to read back in exact same order as we wrote them.
Output:


Writing Objects Begin...
Name::Jack Age::23
Name::Jill Age::25
Writing Objects Exit...
Reading Objects Begin...
Name::Jack Age::23
Name::Jill Age::25
Reading Objects Exit...

Notice that there is a warning in your Person class saying – The serializable class Person does not declare a static final serialVersionUID field of type long. There are two 2 ways to add – either add a default serialVersionUID or the generated serialVersionUID. So what is this serialVersionUID? serialVersionUID is used to ensure that same class(That was used during Serialization) is loaded during Deserialization. If a serializable class does not explicitly declare a serialVersionUID, then the serialization runtime will calculate a default serialVersionUID value for that class based on various aspects of the class.
This might lead you to issues in future. Lets test this: comment out the aSerializationBasic.readObjects(); call from your main method of SerializationBasic class, and run it. This will now only serialize the objects in storage.bat. Now change your Person class say add few attribute like gender,phone and save it. Now comment out the aSerializationBasic.writeObjects(); and only call aSerializationBasic.readObjects(); from your main. You will get an java.io.InvalidClassException.
So its always better to have a serialVersionUID in your class.

Serialization with Inheritance

Lets have a Student class that extends our Person class. Note that our Person class is serializable while Student class does’t implements Serializable interface.


package mynotes.serializtion;
public class Student extends Person {

private String id;
 private String stream;

public Student(String id, String name, int age, String stream) {
 super(name, age);
 this.id = id;
 this.stream = stream;

}

public String getId() {
 return id;
 }

public void setId(String id) {
 this.id = id;
 }

public String getStream() {
 return stream;
 }

public void setStream(String stream) {
 this.stream = stream;
 }

@Override
 public String toString() {
 return "Name::" + super.getName() + " Age::" + super.getAge() + " Id::"
 + this.id + " Stream::" + this.stream;
 }

}

make necessary changes in you SerializationBasic class to now serialize Students object rather than Person and reading.
Output:


Writing Objects Begin...
Name::Jack Age::23 Id::123 Stream::CS
Name::Jill Age::25 Id::124 Stream::IT
Writing Objects Exit...
Reading Objects Begin...
Name::Jack Age::23 Id::123 Stream::CS
Name::Jill Age::25 Id::124 Stream::IT
Reading Objects Exit...

This proves : When the superclass is serializable, so is the subclass, by virtue of inheritance.

Now reverse it, remove implementation from Person and add implementation in Student i.e now superclass is not Serializable.
Output:


Writing Objects Begin...
Name::Jack Age::23 Id::123 Stream::CS
Name::Jill Age::25 Id::124 Stream::IT
Writing Objects Exit...
Reading Objects Begin...
Name::null Age::0 Id::123 Stream::CS
Name::null Age::0 Id::124 Stream::IT
Reading Objects Exit...

Notice the name and age has been intialize to dfault values which proves : If any superclass of an object is not serializable, then the normal creation procedure using constructors is run, starting at the first nonserializable superclass, all the way up to the Object class. This means that the superclass attributes are not serialized.

Suppose super class of a new class implement Serializable interface, how can you avoid child class to being serialized?
The answer is your child class will be Serializable and that cannot be stopped. However, there is a workaround here. You have to implement following method in your child class (Student) that will throw NotSerializableException/IOException/ClassNotFoundException :


private void writeObject(ObjectOutputStream oos) throws NotSerializableException {
 throw new NotSerializableException();
 }

private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
 throw new IOException();
 }

Note that these methods are not of object class. If you try to serialize now you will get an exception.

Which kind of variables is not serialized during Java Serialization? – static and transient

Since static variables belong to the class and not to an object they are not the part of the state of object so they are not saved during Java Serialization process. As Java Serialization only persist state of object and not object itself. Transient variables are also not included in java serialization process and are not the part of the object’s serialized state. These variables initialize back to the default one when deserializing.

What happens to compound objects containing references to other objects?

If you try to serialize an object of a class which implements Serializable, but the object includes a reference to an non- Serializable class then a NotSerializableException’ will be thrown at runtime.

Grab all the code from my GitHub repository.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: