riven

Riven

Riven

Serialization in java with example

Serialization is a crucial concept in Java that allows you to convert an object into a byte stream, which can then be easily saved to a file or transmitted over a network. This process is particularly important for applications that require the storage or transfer of object state. 

What is Serialization?

Serialization is the process of converting an object into a byte stream, allowing it to be easily saved to disk or sent over a network. The primary goal is to preserve the state of an object, so it can be reconstructed later. Conversely, the process of reconstructing an object from a byte stream is called deserialization.

Why Use Serialization?

  1. Persistence: Save the state of an object to a file for later retrieval.
  2. Communication: Send objects over a network in a form that can be reconstructed on the receiving end.
  3. Caching: Store objects in memory for quick retrieval without the need for recomputation.

Use Cases for Serialization

  • Saving application state (e.g., game state, user preferences)
  • Sending objects over a web service or API
  • Storing session data in distributed systems

The Serializable Interface

In Java, serialization is implemented through the Serializable interface. To make a class serializable, you need to implement this interface.

 
				
					import java.io.Serializable;

public class MyClass implements Serializable {
    private static final long serialVersionUID = 1L; // Recommended
    private String name;
    private int age;

    // Constructor, getters, and setters
}
				
			

serialVersionUID

The serialVersionUID is a unique identifier for each class. It is used during deserialization to ensure that a loaded class corresponds exactly to a serialized object. If no serialVersionUID is declared, Java will generate one based on various aspects of the class, which can lead to issues if the class definition changes.

Example of a Serializable Class

				
					import java.io.Serializable;

public class Employee implements Serializable {
    private static final long serialVersionUID = 1L; // Unique identifier
    private String name;
    private int id;

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

    @Override
    public String toString() {
        return "Employee{" + "name='" + name + '\'' + ", id=" + id + '}';
    }
}
				
			

Serialization Process

The serialization process in Java can be done using the ObjectOutputStream class, which is used to write the object to an output stream.

Steps to Serialize an Object

  1. Create an instance of FileOutputStream to specify the destination file.
  2. Wrap it with ObjectOutputStream.
  3. Call the writeObject() method to serialize the object.
  4. Close the streams.

Example: Serializing an Object

Here’s a complete example demonstrating how to serialize an Employee object to a file.

Code Example

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

public class SerializationExample {
    public static void main(String[] args) {
        Employee employee = new Employee("John Doe", 12345);

        try (FileOutputStream fileOut = new FileOutputStream("employee.ser");
             ObjectOutputStream out = new ObjectOutputStream(fileOut)) {

            out.writeObject(employee); // Serialize the object
            System.out.println("Serialized data is saved in employee.ser");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
				
			

Explanation

  1. Creating an Employee Object: An instance of Employee is created.
  2. FileOutputStream: A file output stream is created to specify the file destination.
  3. ObjectOutputStream: An ObjectOutputStream wraps the FileOutputStream.
  4. writeObject() Method: This method serializes the employee object and writes it to the file.
  5. Exception Handling: IOExceptions are caught and handled.
  6. Try-with-resources: The try-with-resources statement automatically closes the streams.

Deserialization Process

Deserialization is the process of reconstructing the object from the byte stream. This is done using the ObjectInputStream class.

Steps to Deserialize an Object

  1. Create an instance of FileInputStream to specify the source file.
  2. Wrap it with ObjectInputStream.
  3. Call the readObject() method to deserialize the object.
  4. Close the streams.

Example: Deserializing an Object

Here’s a complete example demonstrating how to deserialize an Employee object from a file.

Code Example

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

public class DeserializationExample {
    public static void main(String[] args) {
        Employee employee = null;

        try (FileInputStream fileIn = new FileInputStream("employee.ser");
             ObjectInputStream in = new ObjectInputStream(fileIn)) {

            employee = (Employee) in.readObject(); // Deserialize the object
            System.out.println("Deserialized Employee: " + employee);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
				
			

Explanation

  1. FileInputStream: A file input stream is created to read from the specified file.
  2. ObjectInputStream: An ObjectInputStream wraps the FileInputStream.
  3. readObject() Method: This method reads the byte stream from the file and reconstructs the Employee object.
  4. Casting: The returned object is cast to Employee.
  5. Exception Handling: Both IOException and ClassNotFoundException are caught.

Handling Transient Fields

Sometimes, you may want to exclude certain fields from serialization. This can be achieved using the transient keyword. Any field marked as transient will not be serialized.

Example: Using Transient Fields

				
					import java.io.Serializable;

public class User implements Serializable {
    private static final long serialVersionUID = 1L;
    private String username;
    private transient String password; // Will not be serialized

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" + "username='" + username + '\'' + ", password='" + password + '\'' + '}';
    }
}
				
			

Serialization and Deserialization Example with Transient

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

public class UserExample {
    public static void main(String[] args) {
        User user = new User("john_doe", "password123");

        // Serialization
        try (FileOutputStream fileOut = new FileOutputStream("user.ser");
             ObjectOutputStream out = new ObjectOutputStream(fileOut)) {

            out.writeObject(user);
            System.out.println("Serialized User: " + user);
        } catch (IOException e) {
            e.printStackTrace();
        }

        // Deserialization
        try (FileInputStream fileIn = new FileInputStream("user.ser");
             ObjectInputStream in = new ObjectInputStream(fileIn)) {

            User deserializedUser = (User) in.readObject();
            System.out.println("Deserialized User: " + deserializedUser);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
				
			

Explanation

  1. Transient Field: The password field is marked as transient, so it will not be saved during serialization.
  2. Serializations and Deserialization: The serialized user will have a null value for the password upon deserialization.

Custom Serializations

In some cases, you may want to control the serialization and deserialization process. This can be done by defining custom methods in your class.

Custom Methods

  1. writeObject(java.io.ObjectOutputStream out): This method is called during serialization. You can override this method to customize the serialization process.
  2. readObject(java.io.ObjectInputStream in): This method is called during deserialization. You can override this method to customize the deserialization process.

Example: Custom Serializations

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

public class Address implements Serializable {
    private static final long serialVersionUID = 1L;
    private String street;
    private String city;

    public Address(String street, String city) {
        this.street = street;
        this.city = city;
    }

    private void writeObject(ObjectOutputStream out) throws IOException {
        out.defaultWriteObject(); // Write default fields
        out.writeUTF("Country: USA"); // Custom field
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject(); // Read default fields
        String country = in.readUTF(); // Read custom field
        System.out.println("Deserialized Country: " + country);
    }
}
				
			

Advantages of Serializations

  1. Ease of Use: Java’s serializations mechanism simplifies object persistence.
  2. Network Communication: Serializations allows easy transmission of objects over a network.
  3. Flexibility: Custom serializations gives developers control over the process.

Disadvantages of Serializations

  1. Performance Overhead: Serializations can introduce performance costs, especially with large objects.
  2. Versioning Issues: Changes in the class structure can lead to InvalidClassException if serialVersionUID is not managed properly.
  3. Security Risks: Deserializing untrusted data can lead to security vulnerabilities.

Related topic

Java Inheritance with example
Java inheritances with example Inheritances is a fundamental concept in object-oriented programming (OOP)...
listiterator in java with example
listiterator in java with example The ListIterator in Java is a powerful interface that allows you to...
Java synchronization
Java synchronizations What is Synchronizations? Synchronizations in Java is a technique used to control...
Streams in java
Stream in java 8 with example Introduced in Java 8, the Stream API provides a modern and efficient way...
Java try-catch block
Java try-catch blocks Java is designed with a robust exception handling mechanism that helps manage errors...
Java method overriding
Java method overriding Method overriding is a fundamental concept in object-oriented programming (OOP)...
AWT panel in java
What is AWT Panel in Java? A Panel in Java refers to an instance of the JPanel class, which is part of...
Encapsulation in java
Java Encapsulation Encapsulation is one of the four fundamental Object-Oriented Programming (OOP) concepts,...
Return Statement in java with example
Return statement in java with example The return statement in Java is a fundamental aspect of the language...
Hierarchical inheritance java
Hierarchical inheritance java Hierarchical inheritance occurs when one superclass has multiple subclasses....