The whole concept of serialization works on versioning. If you save a class object using one version of the class but attempt to deserialize using a newer or different version of the class deserialization might fail.

When you class structure can change in between you serialize the instance and go again to de-serialize it. Changed structure of class will cause JVM to give exception while de-serializing process.This problem can be solved only by adding a unique serial version id to class. It will prevent the compiler to throw the exception by telling that both classes are same, and will load the available instance variables only.

The serialization runtime associates with each serializable class a version number, called a serialVersionUID, which is used during deserialization to verify that the sender and receiver of a serialized object have loaded classes for that object that are compatible with respect to serialization. If the receiver has loaded a class for the object that has a different serialVersionUID than that of the corresponding sender’s class, then deserialization will result in an InvalidClassException. A serializable class can declare its own serialVersionUID explicitly by declaring a field named “serialVersionUID” that must be static, final, and of type long

 static final long serialVersionUID = 69L;

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, as described in the Java(TM) Object Serialization Specification

What is Serialization?
Serialization is the conversion of an object to a series of bytes, so that the object can be easily saved to persistent storage or streamed across a communication link.The byte stream can then be deserialized – converted into a replica of the original object.In Java, the serialization mechanism is built into the platform, but you need to implement the Serializable interface to make an object serializable.

You can also prevent some data in your object from being serialized by marking the attribute as transient.

Finally you can override the default mechanism, and provide your own; this may be suitable in some special cases.

private void writeObject(ObjectOutputStream out) throws IOException;
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException;

This way you can create your own custom serialization to make it more “whatever” (safe, fast, rare, easy etc. )

It is important to notice that what gets serialized is the “value” of the object, or the contents, and not the class definition.

import java.util.*;

// This class implements "Serializable" to let the system know
// it's ok to do it. You as programmer are aware of that.
public class SerializationSample implements Serializable {

    // These attributes conform the "value" of the object.

    // These two will be serialized;
    private String aString = "The value of that string";
    private int    someInteger = 0;

    // But this won't since it is marked as transient.
    private transient List<File> unInterestingLongLongList;

    // Main method to test.
    public static void main( String [] args ) throws IOException  { 

        // Create a sample object, that contains the default values.
        SerializationSample instance = new SerializationSample();

        // The "ObjectOutputStream" class have the default 
        // definition to serialize an object.
        ObjectOutputStream oos = new ObjectOutputStream( 
                               // By using "FileOutputStream" we will 
                               // Write it to a File in the file system
                               // It could have been a Socket to another 
                               // machine, a database, an in memory array, etc.
                               new FileOutputStream(new File("o.ser")));

        // do the magic  
        oos.writeObject( instance );
        // close the writing.
        oos.close();
    }
}

Real World Example
ATM: When the account holder tries to withdraw money from the server through ATM, the account holder information like withdrawl details will be serialized and sent to server where the details are deserialized and used to perform operations.

How serialization is performed in java.

  1. Implement “java.io.Serializable” interface.(marker interface so no method to implement)
  2. Persist the object : Use java.io.ObjectOutputStream class, a filter stream which is a wrapper around a lower-level byte stream. (to write Object to file systems or transfer a flattened object across a network wire and rebuilt on the other side.)
    1. writeObject(<>) – to write an object
    2. readObject() – to read an serialized Object

When you serialize an object, only the object’s state will be saved, not the object’s class file or methods.

What are the Steps when object is serialized and de-serialized?

  1. First writes the serialization stream magic data
  2. Then it writes out the metadata of the class associated with an instance.( length of the class, the name of the class, serialVersionUID)
  3. Then it recursively writes out the metadata of the superclass until it finds java.lang.object.
  4. Then starts with the actual data associated with the instance.
  5. Finally writes the data of objects associated with the instance starting from metadata to actual content.

How not to serialize any field in class.
Use transient keyword

When child class is serialized does parent class get serialized?
No, Only meta data of parents get serialized till object class.

When parent is serialized does child class get serialized?
Yes, by default child class also get serialized.

How to avoid child class from getting serialized?
Override writeObject and readObject method and throw NotSerializableException exception.also you can mark all fields transient in child class.

Some system-level classes such as Thread, OutputStream, and its subclasses, and Socket are not serializable.

If you have a child class which implements serializable and parent class is not serializable then parent class will be reset to the values they were given during the original construction of the object

 
class Cat
{ 
 public String name = "Cat";
} 

class Tiger extends Cat implements Serializable 
{ 
 public int weight; 

 Tiger(int pWeight, String pName)
 {
   name   = pName;
   weight = pWeight;
 }
} 

class SerialTest
{
 public static void main(String args[])
 {
   Tiger  objTiger = new Tiger(150, "Bengal");
   sysout("Before Serialization : Weight -"+ objTiger.getWeight + " Name -"+ objTiger.getName); 
 }
 
}

Output

 Before Serialization : Weight - 150 Name - Bengal 
 After Serialization : Weight - 150  Name - Cat

After serialization the Parent class Cat Name would be set to Original name which is Cat.This is because non-serializable class constructor will run.

 class Animal implements Serializable
 { 
   transient String swims = "Y";
 }

When the Animal has deserialized the value of swims would be set to null since it is marked as transient.

If you serialize a collection(ArrayList, LinkedList) or an array, every element must be Serializable. If any element in the collection is non-serializable then serialization fails. Collection interfaces are non serializable(List,Map) whereas concrete collection classes are serializable(ArrayList, LinkedList)

Static Variables are not serializable
Static variables are not saved as part of object state because they do not belong to object they belong to Class

What are serializable and not serializable

  1. Instance Variables: These variables are serialized, so during deserialization we will get back the serialized state.
  2. Static Variables: These variables are not serialized, So during deserialization static variable value will loaded from the class.(Current value will be loaded.)
  3. transient Variables: transient variables are not serialized, so during deserialization those variables will be initialized with corresponding default values (ex: for objects null, int 0).
  4. Super class variables: If super class also implemented Serializable interface then those variables will be serialized, otherwise it won’t serialize the super class variables. and while deserializing, JVM will run default constructor in super class and populates the default values. Same thing will happen for all superclasses.