Saturday, 25 April 2015

What Is Serialization in Java? Uses, Examples, and Interview Questions

        Java Serialization is the process of converting a Java object into a byte stream so that it can be sent over a network, saved to a file, or stored in a database for later use.

Deserialization is the reverse process of converting a byte stream back into the original Java object so that it can be used by the application.


Serialization In Java
       Image: Serialization & Deserialization Process

      If you want the objects of a class to be serializable, all you need to do is implement the java.io.Serializable interface. Serializable is a marker interface, which means it does not contain any methods or fields to implement.

The serialization and deserialization processes are performed using the ObjectOutputStream and ObjectInputStream classes, respectively. Therefore, all you need is a wrapper around these classes to either write the object to a file or transmit it over a network.

Let's look at a simple serialization example.


java.io.Serializable Interface:

    package com.adnblog;
    import java.io.Serializable;

    public class Student implements Serializable {

            private static final long serialVersionUID = 6470090944414208496L;
            private String name;
            private int id;
            transient private String address;
          
            @Override
            public String toString(){
                     return     "Student{name="+name+",id="+id+",address="+address+"}";
            }

            //getter and setter methods
            public String getName() {
                     return name;
            }
            public void setName(String name) {
                    this.name = name;
            }

            public int getId() {
                    return id;
            }
            public void setId(int id) {
                    this.id = id;
            }

            public String getAddress() {
                   return address;
            }
            public void setAddress(String address) {
                    this.address = address;
            }
     } 

  For a class to be serialized successfully, the following two conditions must be met:
  1. The class must implement the java.io.Serializable interface.

  2. All the fields of the class must also be serializable. If a field is not serializable, it should be marked as transient. In the above Student class, the address field is non-serializable and should therefore be declared as transient.

Once a class implements Serializable, its objects can be written to any OutputStream, such as a file or a socket connection. To do this, create an instance of java.io.ObjectOutputStream by passing an existing OutputStream object to its constructor.

     package com.adnblog;

     import java.io.FileOutputStream;
     import java.io.ObjectOutputStream;

     public class SerializeObject {
           public static void main(String[] args) {
                  String filename = "Serialize.ser";    //give the file name with file name
                  Student st = new Student();
                  st.setName("Anil");
                  st.setId(24);
                  st.setAddress("A/P-Sonyal,Tal-Jath,Dist-Sangli");

                  // save the object to file
                  FileOutputStream fos = null;
                  ObjectOutputStream out = null;
                  try {
                       fos = new FileOutputStream(filename);
                       out = new ObjectOutputStream(fos);
                       out.writeObject(st);
                  } catch (Exception ex) {
                      ex.printStackTrace();
                  } finally {
                       if(out != null) {
                             out.close();
                       }
                  }
            }
     }

Deserialization

Deserialization is the process of converting a byte stream back into the original Java object so that it can be used by the application.

Below is an example of Java object deserialization. First, create a FileInputStream for the file that contains the serialized object's byte stream, and then pass it to the constructor of ObjectInputStream. The readObject() method reads the byte stream from the file and reconstructs the original Java object.


          package com.adnblog;

          import java.io.FileInputStream;
          import java.io.ObjectInputStream;

          public class DeserializeObject {
                   public static void main(String[] args) {
                            String filename = "Serialize.ser";   
                            Student st = null;
                               // read the object from file
                            FileInputStream fis = null;
                            ObjectInputStream ois = null;
                            try {
                                   fis = new FileInputStream(filename);
                                   ois = new ObjectInputStream(fis);
                                   st = (Student) ois.readObject();
                            } catch (Exception ex) {
                                          ex.printStackTrace();
                            }
                            finally {
                                       if(ois != null) {
                                             ois.close();

                                      }

                            }
                            System.out.println(st);
                   }
           }

Uses of Serialization

1. Banking Example

Consider an ATM transaction where an account holder requests to withdraw money. The account holder's information, along with the withdrawal details, can be serialized (marshalled into a byte stream) and sent to the server. The server then deserializes (unmarshals) the byte stream back into a Java object and processes the transaction.

This approach reduces the number of network calls because the complete object is transmitted in a single request, eliminating the need for the server to make additional requests for related information.

2. Stock Market Example

Suppose a user wants to receive the latest stock updates immediately upon request. To achieve this, the latest stock information can be serialized and stored in a file whenever new data becomes available. When the user requests the information, the application can deserialize the object from the file and return the data instantly.

This approach improves performance by avoiding repeated database queries and expensive computations for every user request, resulting in a faster response time.

Common Uses of Serialization

  1. Convert a Java object into a byte stream so that it can be stored in a database or file for persistence.

  2. Enable communication between two JVMs by serializing objects and transferring them over the network.

  3. Send a Java object across a network as a byte stream through serialization, and deserialize it at the receiving end to reconstruct the same object in its original state.

  4. Cache objects by serializing them instead of keeping them in memory, helping to reduce memory usage.

Serialization and Deserialization Interview Questions

1) What is serialVersionUID, and why should we use it?

The serialization runtime associates every serializable class with a version number called serialVersionUID. During deserialization, this version number is used to verify that the sender and receiver have loaded compatible versions of the class.

If the serialVersionUID of the serialized object does not match the serialVersionUID of the receiving class, the deserialization process fails with an InvalidClassException.

A serializable class can explicitly declare its own serialVersionUID as follows:

private static final long serialVersionUID = 42L;

Declaring serialVersionUID explicitly is considered a best practice because it provides version control and prevents unexpected InvalidClassExceptions when the class definition changes.

2) Do we need to implement any methods of the Serializable interface to make an object serializable?

No. The Serializable interface is a marker interface, which means it does not declare any methods. A class becomes serializable simply by implementing the java.io.Serializable interface.

3) How can we make a field non-serializable?

Sometimes, you may not want to serialize certain fields. For example, a field may contain sensitive information such as a password, or its value may always be loaded from a database or another external source.

To exclude a field from serialization, declare it with the transient keyword.

For example:

private transient String password;

Fields marked as transient are ignored during serialization and are not included in the serialized byte stream.

        transient private String address;

       Also the static fields are not serialized. Actually there is no point in serializing static fields as static fields do not represent object state but represent class state and it can be modified by any other object. Lets assume that you have serialized a static field and its value and before deserialization of the object, the static field value is changed by some other object. Now the static field value that is serialized/stored is no more valid. Hence it make no point in serializing the static field.

Note :-- The static and transient fields can not be serialized.