Table of contents
1.
Introduction
2.
What is Serialization in Java?
3.
Advantages of Java Serialization
4.
Serializable Interface
4.1.
Syntax 
5.
Method of ObjectOutputStream class
6.
Method of ObjectInputStream class
7.
Example of Serialization in Java
7.1.
Output
7.2.
Explanation
8.
What is De-Serialization in Java?
9.
Example of Deserialization in Java
9.1.
Output
9.2.
Explanation
10.
Why Serialize and Deserialize Objects in Java?
11.
Handling Exceptions during Serialization and Deserialization
12.
Java Serialization with Inheritance (IS-A Relationship)
13.
Java Serialization with Aggregation (HAS-A Relationship)
14.
Java Serialization with the static data member
15.
Transient Keyword
15.1.
Syntax
16.
Version Control with serialVersionUID
17.
Frequently Asked Questions
17.1.
How can serialVersionUID help with version control in serialization?
17.2.
Which is the most secure way to defend against deserialization attacks?
17.3.
Why do we use Serialization and Deserialization in Java?
17.4.
Why do we need serialization?
18.
Conclusion
Last Updated: Mar 27, 2024
Medium

Serialization and De-Serialization in Java

Author Narayan Mishra
2 upvotes
Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction

Serialization and deserialization are essential concepts in Java, particularly when dealing with object persistence and data transfer between different systems.

Serialization and De-Serialization in Java

You might wonder what this has to do with serialization and deserialization in Java.

In order to transfer the Java object between platforms, you need to first convert it into a form that will allow us to transfer it easily. This process is called Serialization. Constructing the original object from this current form is called deserialization.

In this article, we will learn about Serialization and Deserialization in Java, their properties, the advantages of serialization, and how to implement it.

Also see, Swap Function in Java

What is Serialization in Java?

Serialization in Java is a process of converting the state of a Java object into a byte stream. You can store the byte stream in memory, a file, or a database. The byte stream can then be reverted into a copy of the object using deserialization.

Here, we have used two very important terms:

  • State: The state of the Java object implies the object's value or data of the object.
     
  • Byte Stream: Byte stream refers to the java I/O(input-output) stream of 8-bit bytes, which you can use to read from or write to.
    The byte streams are platform-independent, which allows us to serialize an object on one platform and deserialize it on another. 
     

Advantages of Java Serialization

  • Data Persistence: Objects can be saved to files, enabling long-term data storage.
     
  • Object Cloning: Serialization allows the creation of deep object copies.
     
  • Platform Independence: Serialized objects can be transferred across different platforms.
     
  • Security: Control over which classes can be serialized for secure data transfer.
     
  • Integration: Seamlessly integrated into Java with standard libraries.
     
  • Caching: Objects can be cached in memory for improved performance.

Serializable Interface

The serializable interface marker interface informs the JVM that the object can be serialized and deserialized. Let us look at the syntax to understand this.

Syntax 

import java.io.Serializable;
public class ClassName implements Serializable {
    // Fields and Getters and setters
}
You can also try this code with Online Java Compiler
Run Code


Now you might be thinking about how we can implement the serialization in Java. Let us understand this with the help of an example.

It's important to note that the serializable interface has no data members or methods. Thus, the interface Serializable is a type of Marker Class part of the java.io package.

Serializable Interface

Method of ObjectOutputStream class

The `ObjectOutputStream` class in Java facilitates object serialization. Its methods include `writeObject(obj)` for writing serializable objects, `flush()` to flush the output stream, and `close()` to close the stream. `defaultWriteObject()` and `writeFields()` assist in custom serialization. `annotateClass()` and `annotateProxyClass()` annotate class descriptors. These methods enable developers to manage object serialization, custom serialization, and stream control.

Code:

import java.io.*;

public class hello {

public static void main(String[] args) {
String text = "Coding Ninjas";
int number = 1000000000;

try {

FileOutputStream out = new FileOutputStream("test.txt");
ObjectOutputStream oout = new ObjectOutputStream(out);

oout.writeObject(text);
oout.writeObject(number);

oout.close();

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("test.txt"));

System.out.println("" + (String) ois.readObject());
System.out.println("" + ois.readObject());

} catch (Exception ex) {
ex.printStackTrace();
}

}
}
You can also try this code with Online Java Compiler
Run Code

Output:

Coding Ninjas
1000000000

Method of ObjectInputStream class

The `ObjectInputStream` class in Java is used for deserializing objects. Its key methods include `readObject()` to read serialized objects, `close()` for stream closure, and `read()` for reading bytes. `readUnshared()` reads an unshared object. `resolveClass()` allows class resolution during deserialization. `registerValidation()` is used for object validation. These methods enable the deserialization of objects, stream management, and customization of deserialization logic in Java programs.

Code:

import java.io.*;

public class hello {

public static void main(String[] args) {
try {
// Create an ObjectInputStream for the file we want to read from
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("test.txt"));

// Read and print objects from the file
String text = (String) ois.readObject();
int number = (int) ois.readObject();

System.out.println("String: " + text);
System.out.println("Integer: " + number);

// Close the ObjectInputStream
ois.close();

} catch (Exception ex) {
ex.printStackTrace();
}
}
}
You can also try this code with Online Java Compiler
Run Code

Output:

String: Coding Ninjas
Integer: 1000000000

Example of Serialization in Java

Here is an example to understand the serialization process in Java. 


import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;


class Ninjas implements Serializable {
    // Fields
    private String ninjasName;
    private int ninjasAge;
    private int ninjasQuestionSolvedCount;


    // Ninjas Constructor
    public Ninjas(String ninjasName, int ninjasAge, int ninjasQuestionSolvedCount) {
        this.ninjasName = ninjasName;
        this.ninjasAge= ninjasAge;
        this.ninjasQuestionSolvedCount = ninjasQuestionSolvedCount;
    }
// Getters
public String getNinjasName() {
return ninjasName;
}

public int getNinjasAge() {
return ninjasAge;
}

public int getNinjasQuestionSolvedCount() {
return ninjasQuestionSolvedCount;
}

public void setNinjasName(String ninjasName) {
// Setter for ninjasName
this.ninjasName = ninjasName;
}

public void setNinjasAge(int ninjasAge) {
// Setter for ninjasAge
this.ninjasAge= ninjasAge;
}

public void setNinjasQuestionSolvedCount(int ninjasQuestionSolvedCount) {
// Setter for ninjasQuestionSolvedCount
this.ninjasQuestionSolvedCount = ninjasQuestionSolvedCount;
}
}

public class SerializationProcess{
    public static void main(String[] args) {
        // Creating Ninjas object and passing three parameters
        Ninjas ninjas = new Ninjas("Kanak Rana",20,150);

        try {
            // Using FileOutputStream for ninjas.ser
            FileOutputStream fileOutput = new FileOutputStream("ninjas.ser");
            ObjectOutputStream objectOutput = new ObjectOutputStream(fileOutput);
            objectOutput.writeObject(ninjas);
            System.out.println("Ninjas! Object is serialized...");
            objectOutput.close();
            fileOutput.close();
        } catch (IOException i) {
            i.printStackTrace();
        }
    }
}
You can also try this code with Online Java Compiler
Run Code

Output

Ninjas! Object is serialized…

In the ninjas.ser file, we will see the object is converted into bytestream:

output

Explanation

In this example, we have created a class called Ninjas. It implements the Serializable interface. Then we have used several fields to pass the information about a ninja. In the main class, we have used FileOutputStream to save it to a file named ninjas.ser. Then used ObjectOutputStream to write the object into the file ninjas.ser.

Also read, Java Ioexception

What is De-Serialization in Java?

De-Serialization in Java is the reverse process of serialization which converts the byte stream to an actual java object in memory. Deserialization requires the class  ObjectInputStream, which we use to read the byte stream.

It is used when we have serialized objects. To deserialize an object, use the ObjectInputStream class from the java.io package. Let us understand this with the help of an example.

Example of Deserialization in Java

Here is an example to understand deserialization in Java:

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

class Ninjas implements Serializable {
    // Fields
    private String ninjasName;
    private int ninjasAge;
    private int ninjasQuestionSolvedCount;
   
    // Constructor
    public Ninjas(String ninjasName, int ninjasAge, int ninjasQuestionSolvedCount) {
this.ninjasName = ninjasName;
this.ninjasAge = ninjasAge;
this.ninjasQuestionSolvedCount = ninjasQuestionSolvedCount;
     }

     // Getters and setters
     public String getNinjasName() {
return ninjasName;
     }

     public void setNinjasName(String ninjasName) {
this.ninjasName = ninjasName;
     }

     public int getNinjasAge() {
return ninjasAge;
     }

     public void setNinjasAge(int ninjasAge) {
this.ninjasAge = ninjasAge;
     }

     public int getNinjasQuestionSolvedCount() {
return ninjasQuestionSolvedCount;
     }

      public void setNinjasQuestionSolvedCount(int ninjasQuestionSolvedCount) {
this.ninjasQuestionSolvedCount = ninjasQuestionSolvedCount;
      }

}

public class DeserializationProcess{
    public static void main(String[] args) {
        try {
// Using FileInputStream for deserialization
            FileInputStream fileInput = new FileInputStream("ninjas.ser");
            ObjectInputStream objectInput = new ObjectInputStream(fileInput);
            
            // Reading data of object ninjas
            Ninjas ninjas= (Ninjas)objectInput.readObject();
            System.out.println("Ninjas! Object is deserialized..");
            System.out.println("Here are the details about the ninja: ");
            System.out.println("Name of the Ninja: " + ninjas.getNinjasName());
            System.out.println("Age of the Ninja: " + ninjas.getNinjasAge());
            System.out.println("Question solved by the Ninja: " + ninjas.getNinjasQuestionSolvedCount());
            objectInput.close();
            fileInput.close();
        } 
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}
You can also try this code with Online Java Compiler
Run Code

Output

Ninjas! Object is deserialized..
Here are the details about the ninja: 
Name of the Ninja: Kanak Rana
Age of the Ninja: 20
Question solved by the Ninja: 150

Explanation

In this example, we are reading serialized Ninjas object from a file named ninjas.ser and restoring it. It then prints the name, age, and the questions solved by the ninja.

Why Serialize and Deserialize Objects in Java?

Serialized and deserialized objects in Java used for different purposes:

  • Data persistence: Serialization enables storing an object's state on disk for later retrieval.
     
  • Data transfer: Serialized objects can be sent across networks, allowing communication between different systems.
     
  • Deep cloning: Serialization and deserialization can create a deep copy of an object, which is useful when cloning complex objects.

Handling Exceptions during Serialization and Deserialization

There are several exceptions you may encounter during serialization and deserialization:

  • IOException: This exception occurs when there is an issue with I/O operations.
     
  • ClassNotFoundException: This exception is thrown when the JVM cannot find the corresponding class for the deserialized object.

To handle these exceptions, use try-catch blocks as shown in the serialization and deserialization examples.

Java Serialization with Inheritance (IS-A Relationship)

Java serialization handles inheritance (IS-A relationship) by automatically serializing the superclass and its fields when serializing a subclass.

import java.io.Serializable;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.FileInputStream;
import java.io.ObjectInputStream;

class Person implements Serializable {
private int id;
private String name;

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

public int getId() {
return id;
}

public String getName() {
return name;
}
}

class Student extends Person implements Serializable {
private String course;
private int fee;

public Student(int id, String name, String course, int fee) {
super(id, name);
this.course = course;
this.fee = fee;
}

public String getCourse() {
return course;
}

public int getFee() {
return fee;
}
}

public class hello {
public static void main(String args[]) {
try {
// Creating the object
Student student = new Student(41, "Aditya", "Computer Science", 100000);

// Creating stream and writing the object
FileOutputStream fileOutputStream = new FileOutputStream("student.ser");
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(student);
objectOutputStream.flush();

// Closing the stream
objectOutputStream.close();
System.out.println("Serialization successful");
} catch (Exception e) {
System.out.println(e);
}

try {
// Creating stream to read the object
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("student.ser"));
Student deserializedStudent = (Student) objectInputStream.readObject();

// Printing the data of the serialized object
System.out.println("Student ID: " + deserializedStudent.getId());
System.out.println("Student Name: " + deserializedStudent.getName());
System.out.println("Course: " + deserializedStudent.getCourse());
System.out.println("Fee: " + deserializedStudent.getFee());

// Closing the stream
objectInputStream.close();
} catch (Exception e) {
System.out.println(e);
}
}
}
You can also try this code with Online Java Compiler
Run Code

Output:

output

Java Serialization with Aggregation (HAS-A Relationship)

Java Serialization with Aggregation (HAS-A Relationship) involves serializing objects that have a "HAS-A" relationship with other objects. In this scenario, an object contains references to other objects as its attributes. 

class Address {
   String houseNumber;
   String city;
   String state;
   public Address(String houseNumber, String city) {
       this.houseNumber = houseNumber;
       this.city = city;
   }
}
You can also try this code with Online Java Compiler
Run Code

 

import java.io.Serializable;
public class Employee implements Serializable {
   int employeeId;
   String employeeName;
   Address employeeAddress; // HAS-A relationship
   public Employee(int employeeId, String employeeName) {
       this.employeeId = employeeId;
       this.employeeName = employeeName;
   }
}
You can also try this code with Online Java Compiler
Run Code

Java Serialization with the static data member

In Java, when you serialize an object, the static data members (also known as class-level variables) are not serialized. This is because static members belong to the class, not to individual objects, and they are not part of the object's state. Instead, they are associated with the class itself. Therefore, static members are not saved as part of the serialized object.

import java.io.*;

class MyClass implements Serializable {
private int instanceVar;
private static int staticVar;

public MyClass(int instanceVar) {
this.instanceVar = instanceVar;
}

public static void setStaticVar(int value) {
staticVar = value;
}

public static int getStaticVar() {
return staticVar;
}

@Override
public String toString() {
return "InstanceVar: " + instanceVar + ", StaticVar: " + staticVar;
}
}

public class hello {
public static void main(String[] args) {
try {
// Create an object and set static variable
MyClass obj = new MyClass(42);
obj.setStaticVar(100);

// Serialize the object
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("object.ser"));
out.writeObject(obj);
out.close();

System.out.println("Serialization successful");
} catch (IOException e) {
e.printStackTrace();
}

try {
// Deserialize the object
ObjectInputStream in = new ObjectInputStream(new FileInputStream("object.ser"));
MyClass deserializedObj = (MyClass) in.readObject();
in.close();

// Display the object's values
System.out.println("Deserialized Object: " + deserializedObj);
System.out.println("StaticVar in Deserialized Object: " + deserializedObj.getStaticVar());
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
You can also try this code with Online Java Compiler
Run Code

Output:

Java Serialization with the static data member

Transient Keyword

The transient keyword in Java is used to indicate that a specific instance variable should not be serialized. When an object is deserialized, the transient variables are assigned their default values. Let us understand this with the help of its syntax:

Syntax

import java.io.Serializable;

public class Person implements Serializable {
    private String name;
    
   // age will not be serialized
    private transient int age; 
    // Getters and setters
}

Version Control with serialVersionUID

The serialVersionUID is a unique identifier for a serializable class. It is used during deserialization to verify that the sender and receiver of a serialized object have compatible class definitions. If serialVersionUIDs do not match, an InvalidClassException is thrown. To define a serialVersionUID, add the following declaration to your serializable class:

private static final long serialVersionUID = 1L;

Frequently Asked Questions

How can serialVersionUID help with version control in serialization?

SerialVersionUID ensures that the sender and receiver of a serialized object have compatible class definitions, preventing deserialization errors due to class version mismatches.

Which is the most secure way to defend against deserialization attacks?

The only way to ensure complete protection against insecure deserialization attacks is to reject any serialized objects from an unvetted source (or to accept only the serialized objects derived from a primitive data type).

Why do we use Serialization and Deserialization in Java?

Serialization in Java is used to convert objects into a byte stream for storage or transmission, while deserialization restores objects from the byte stream, enabling data persistence and communication.

Why do we need serialization?

Serialization is needed in Java for data persistence, communication, and storage as it allows objects to be converted into a byte stream that can be easily reconstructed.

Conclusion

In this article, we learned about Serialization and Deserialization in java, their properties, the advantages of serialization, and how to implement serialization in java.

We hope this blog has helped you enhance your knowledge of Serialization and Deserialization in java.

Check out these useful blogs on - 

Refer to our guided paths on Coding Ninjas Studio to learn more about DSA, Competitive Programming, JavaScript, System Design, etc. Enroll in our courses and refer to the mock test and problems available, interview puzzles, take a look at the interview experiences, and interview bundle for placement preparations.

Do upvote our blog to help other ninjas grow.

Happy Reading!!‍

Live masterclass