Serialization in Java – Deserialization in Java

Before we dive into the topic of serialization in java and deserialization in Java, you might want to look at a real-life example first.

Imagine you are talking to your friend over a cellular network. Your voice is audible to your friend who is sitting miles away from your home. You may also know that your voice gets converted into electrical signals which are then propagated to a mobile tower via radio signals. The tower then channels the electrical signal to the specific phone number you are in a connection with.

Your voice goes through a lot of conversions to reach your friend on the other side. Similarly, objects in Java need serialization and deserialization for traveling from one JVM to another. Now that you can relate as to why these concepts are useful, let us start!

Serialization - deserialization in java

Keeping you updated with latest technology trends, Join DataFlair on Telegram

Serialization and Deserialization in Java

Serialization is the process of converting a java object into a stream of bytes. This stream of bytes when received by the end-user gets converted to an object and thus the object is easily transferred from one JVM to another. Note that the byte stream is platform-independent. This means that once you have a stream of bytes you can convert it into an object and run it on any kind of environment.

The JVM allows special privileges to the class which implements the Serializable Interface.

There is a class “ObjectOutputStream” which consists of a method “writeObject”. This method is responsible for converting an object into a stream of Bytes. A similar class “ObjectInputStream” contains a method readObject(). This method essentially converts the byte stream to an object.

Syntax

public final void writeObject(<object>)throws IOException
public final void readObject()throws IOException,ClassNotFoundException

java.io.Serializable Interface

The functions like serialization and deserialization will be impossible to implement if not for the java.io.Serializable Interface. The interface in itself is empty. However, the compiler does grant special privileges to the class if it implements the Serializable interface.

There are certain data types such as strings which implement the interface by default. All wrapper classes implement this interface by default too.

ObjectOutputStream Class in Java

This class is essential for writing objects into streams. Only the classes which implement the Serializable interface can serve as an argument to the methods of this class. This class has methods that convert the object to a byte stream.

Constructor in Java

Now let us look at the constructor of this class.

public ObjectOutputStream(OutputStream out) throws IOException {}

This constructor creates a byte stream that writes to the specific Object stream.

Methods in Java

Now let us look at the methods inside this class. This class primarily houses three methods

  1. public final void writeObject(Object obj) throws IOException {} – useful for writing the object to the ObjectOutputStream.
  2. public void flush() throws IOException {} – This method is responsible for flushing the output stream.
  3. public void close() throws IOException {} – This method is responsible for closing the current output stream.

ObjectInputStream Class in Java

This class has the function of doing the exact opposite function of what the ObjectOutputStream class did. It converts the byte stream to deserialized objects.

Constructor in Java

Now let us look at the constructor of this class.

public ObjectInputStream(InputStream in) throws IOException {}

This constructor is essential because it creates an ObjectInputStream which reads from the InputStream.

Methods in Java

  1. public final Object readObject() throws IOException, ClassNotFoundException{} – This method converts the stream to an object. This simply means that the method reads the object from the incoming input stream.
  2. public void close() throws IOException {} – As the name suggests, this method has the function of closing the ObjectInputStream.

Serialization in Java with Inheritance

While implementing serialization alongside inheritance, there is a very important point to note. All the classes which inherit from the parent class will automatically implement the Serializable interface. Let us look at an example

Java program to illustrate serialization with inheritance:

package com.dataflair.serialdeserial;

import java.io. * ;
class ParentClass implements Serializable {
  int variable1,
  variable2;
  ParentClass() {
    this.variable1 = 50;
    this.variable2 = 60;

  }
}
public class SerialInheritance extends ParentClass

{
  public static void main(String[] args) throws IOException {
    //This class can also have serialization and deserialization methods inside it even if it does not implement the Serializable interface. 
    try {
      ParentClass parentclassob = new ParentClass();
      //Creating stream and writing the object  
      FileOutputStream fout = new FileOutputStream("file.txt");
      ObjectOutputStream out = new ObjectOutputStream(fout);
      out.writeObject(parentclassob);
      out.flush();
      //closing the stream  
      out.close();
      System.out.println("This class can implement the Serializable interface!!");
    }
    catch(Exception e) {
      System.out.println(e);
    }
  }
}

Output

This class can implement the Serializable interface!!

Serialization in Java with Aggregation

If a class has references to another class, all the individual references must implement the Serializable interface. Let us understand this concept better with an example

Java program to illustrate the use of Serialization with Aggregation:

package com.dataflair.serialdeserial;

import java.io. * ;
class ParentClass {
  int variable1,
  variable2;
  ParentClass() {
    this.variable1 = 50;
    this.variable2 = 60;

  }
}
public class SerialInheritance

{
  public static void main(String[] args) throws IOException {
    //This class can also have serialization and deserialization methods inside it even if it does not implement the Serializable interface. 
    try {
      ParentClass parentclassob = new ParentClass();
      //Creating stream and writing the object  
      FileOutputStream fout = new FileOutputStream("file.txt");
      ObjectOutputStream out = new ObjectOutputStream(fout);
      out.writeObject(parentclassob);
      out.flush();
      //closing the stream  
      out.close();
      System.out.println("This class can implement the Serializable interface!!");
    }
    catch(Exception e) {
      System.out.println(e);
    }
  }
}

Output

java.io.NotSerializableException: ParentClass

Serialization in Java with Array or Collection

When we talk about arrays or collections, we must know that when we create an object of these collection classes, it is essential to ensure that they implement the Serializable interface. Simply put, the collections must be serializable. Otherwise, the compiler returns an error. Let us look at an example

Program to illustrate the process of serialization in Java by using arrays:

package com.dataflair.serialdeserial;

import java.io. * ;
class ParentClass {
  int variable1,
  variable2;
  ParentClass() {
    this.variable1 = 50;
    this.variable2 = 60;

  }
}
public class SerialInheritance

{
  public static void main(String[] args) throws IOException {
    //This class can also have serialization and deserialization methods inside it even if it does not implement the Serializable interface. 
    try {
      int arr[] = new int[50];
      ParentClass parentclassob = new ParentClass();
      //Creating stream and writing the object  
      FileOutputStream fout = new FileOutputStream("file.txt");
      ObjectOutputStream out = new ObjectOutputStream(fout);
      out.writeObject(arr);
      out.flush();
      //closing the stream  
      out.close();
      System.out.println("This class can implement the Serializable interface!!");
    }
    catch(Exception e) {
      System.out.println(e);
    }
  }
}

Output

This class can implement the Serializable interface!!

Notice how the array object is serializable.

Serialization in Java with Static Data Member

Static data members get ignored during serialization. This is because the static variables are not a part of the object. We will look at an example of this later in this article.

Transient Keyword in Java

The transient Keyword is useful when you want any non-static variable to get ignored during serialization. After deserialization, the value of the variable will be the default value for that datatype. For example, if an integer datatype was transient, the value of the variable would change to zero(0) after deserialization.
We will see an example where we explain this clearly, later in this article.

Why do we need Java Serialization?

  1. Serialization allows us to transfer objects through a network by converting it into a byte stream.
  2. It also helps in preserving the state of the object.
  3. Deserialization requires less time to create an object than an actual object created from a class. hence serialization saves time.
  4. One can easily clone the object by serializing it into byte streams and then deserializing it.
  5. Serialization helps to implement persistence in the program. It helps in storing the object directly in a database in the form of byte streams. This is useful as the data is easily retrievable whenever needed.

Points to Remember while Implementing the Serializable Interface in Java

  1. All of the associated objects must implement the serializable interface.
  2. You can save non-static data members with the Serializable interface.
  3. A child class doesn’t need to implement the Serializable interface if the parent class has already implemented it.
  4. The serializable interface does not store the values of non-static and transient datatypes.
  5. During deserialization, the constructor of the object remains uncalled.

Serial Version UID in Java

This version UID is unique for every object. Every class which implements the Serializable interface gets a unique Serial Version ID.
This is useful to check whether the sender and receiver of a serialized object is loading the same class or not.

If the UID’s do not match, then the compiler throws an InvalidClassException. If by any chance the receiver loads a different class than the class which is serialized, then the UID’s do not match and the compiler throws an InvalidClassException.

You can explicitly declare a serializable UID for a class. There are certain rules to declare UID. They are:

  1. It should be of a long type.
  2. It should be static.
  3. It should be final.
  4. There are no limitations on the access specifier of the variable. You can use anyone.

If you do not explicitly mention a UID, then the JVM automatically assigns one for you. However, the common access specifier for the Serial version UID is private so that it is non-inheritable.

serialver Command in Java

serialver is a command which is used to get the serial version of a class file. It has a syntax :

serialver <classpath><-show><classname>

Java program to illustrate the use of serialization and deserialization in Java:

package com.dataflair.serialdeserial;
import java.io. * ;

class TestSerializeDeserialize implements Serializable {
  private static final long serialversionUID = 65421233l; //Random value for SerialUID
  transient int transvar;
  static int staticvar;
  int normalvar;
  public TestSerializeDeserialize(int transvar, int staticvar, int normalvar) {
    this.transvar = transvar;
    TestSerializeDeserialize.staticvar = staticvar;
    this.normalvar = normalvar;

  }
}
public class SerializationAndDeserialization {
  //We now declare a method which will print all the data in the previous class
  public static void printdetails(TestSerializeDeserialize obj) {
    System.out.println("The transient variable has a value equal to " + obj.transvar);
    System.out.println("The static variable has a value equal to " + obj.staticvar);
    System.out.println("The normal variable has a value equal to " + obj.normalvar);

  }
  public static void main(String[] args) {
    TestSerializeDeserialize object = new TestSerializeDeserialize(123, 143, 1000);
    String filename = "Serialization.txt";
    try {
      FileOutputStream file = new FileOutputStream(filename);
      ObjectOutputStream out = new ObjectOutputStream(file);

      //now we serialize the object
      out.writeObject(object);
      out.close();
      file.close();

      //Now we shall see how our data looked before serialization
      System.out.println("Serialization performed on the object. Let us see what our data looked like before serialization");
      printdetails(object);

      object.staticvar = 453;
    }
    catch(IOException IOE) {
      System.out.println("IOException caught ->" + IOE.getMessage());
    }
    //We know that the writeObject can throw IOException hence we handle that

    object = null; //resetting the object
    //Now we get to deserialization

    try {
      FileInputStream file = new FileInputStream(filename);
      ObjectInputStream in =new ObjectInputStream(file);

      //Method for deserialization of object
      object = (TestSerializeDeserialize) in .readObject();

      in .close();
      file.close();

      System.out.println("\nThe Object is now deserialized");
      System.out.println("\nThe data after deserialization\n");

      printdetails(object);

    }
    catch(IOException IOE) {
      System.out.println("IOException caught ->" + IOE.getMessage());
    }
    catch(ClassNotFoundException CNFE) {
      System.out.println("ClassNotFoundException caught ->" + CNFE.getMessage());

    }
  }
}

Output

Serialization performed on the object. Let us see what our data looked like before serialization
The transient variable has a value equal to 123
The static variable has a value equal to 143
The normal variable has a value equal to 1000The Object is now deserialized

The data after deserialization

The transient variable has a value equal to 0
The static variable has a value equal to 453
The normal variable has a value equal to 1000

Analyzing the above program, we come across very important observations. They are

  1. As we came to know earlier, the transient variable gets ignored during deserialization. Hence the value of the transvar variable changed to 0 which is the default value for a variable with int datatype.
  2. Similar to the transient variable, the static variable gets ignored during serialization. However, unlike the transient variable, this static variable will store the value specified inside the class. during deserialization.

Advantages of Serialization in Java

  1. This is a built-in feature of Java. Hence you need not use third-party services to implement Serialization.
  2. This concept is easy to understand.
  3. It is customizable as per the programmer’s needs.
  4. This process is universal and all kinds of developers are familiar with the concept.
  5. This allows Java to perform Encryption, Authentication, and Compression and secure Java computing.
  6. Most of the technologies we use daily, rely on serialization.

Disadvantages of Serialization in Java

  1. Sometimes the byte streams do not convert into objects completely which leads to errors.
  2. Whenever you declare a variable as transient, the compiler assigns a memory space to it. But the constructor of the class remains uncalled. This results in a variation of Java Standard Flow.
  3. This process is inefficient when it comes to memory utilization.
  4. Serialization is not useful in applications that need concurrent access without using third party APIs. This is because serialization does not offer any transition control mechanism.
  5. It does not allow fine control when accessing objects.

Best Practices while using Serialization in Java

  1. All serializations should have a “.ser” extension.
  2. Default Serialization should not include static or transient fields.
  3. It is advisable to not serialize extendable classes unless necessary.
  4. You should avoid inner classes while implementing serialization.
  5. Use the Javadoc @serial tag when you are trying to denote serializable fields.

Summary

In this article, we learned about Serialization in java and Deserialization in java, its uses, its implementation. Serialization is essential in everyday programming especially when you have to transfer objects through a network.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.