Serialization and Deserialization in Java

Loading

Serialization and Deserialization in Java are mechanisms used to convert objects into a byte stream (serialization) and reconstruct objects from a byte stream (deserialization). These processes are essential for saving object states to files, sending objects over a network, or storing objects in databases.


1. Serialization

  • Serialization is the process of converting an object into a byte stream.
  • The byte stream can be saved to a file, sent over a network, or stored in a database.
  • To make a class serializable, it must implement the java.io.Serializable interface (a marker interface with no methods).

Steps for Serialization:

  1. Implement the Serializable interface.
  2. Use ObjectOutputStream to write the object to a file or output stream.

Example:

import java.io.*;

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

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

    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + "}";
    }
}

public class SerializationExample {
    public static void main(String[] args) {
        Person person = new Person("Alice", 30);

        try (FileOutputStream fileOut = new FileOutputStream("person.ser");
             ObjectOutputStream out = new ObjectOutputStream(fileOut)) {
            out.writeObject(person); // Serialize the object
            System.out.println("Object serialized and saved to person.ser");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2. Deserialization

  • Deserialization is the process of reconstructing an object from a byte stream.
  • Use ObjectInputStream to read the object from a file or input stream.

Steps for Deserialization:

  1. Use ObjectInputStream to read the object from a file or input stream.
  2. Cast the deserialized object to the appropriate class.

Example:

import java.io.*;

public class DeserializationExample {
    public static void main(String[] args) {
        try (FileInputStream fileIn = new FileInputStream("person.ser");
             ObjectInputStream in = new ObjectInputStream(fileIn)) {
            Person person = (Person) in.readObject(); // Deserialize the object
            System.out.println("Object deserialized: " + person);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

3. Key Points About Serialization

  • Transient Fields: Fields marked as transient are not serialized.
  private transient String password; // This field will not be serialized
  • Static Fields: Static fields are not serialized because they belong to the class, not the object.
  • SerialVersionUID: A unique identifier for the serialized class. It ensures compatibility during deserialization.
  private static final long serialVersionUID = 1L;
  • Custom Serialization: You can override the default serialization behavior by implementing writeObject and readObject methods in your class.

4. Custom Serialization

You can customize the serialization process by implementing the writeObject and readObject methods in your class.

Example:

import java.io.*;

class Person implements Serializable {
    private String name;
    private transient int age; // Transient field

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

    private void writeObject(ObjectOutputStream out) throws IOException {
        out.defaultWriteObject(); // Default serialization
        out.writeInt(age); // Custom serialization for transient field
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject(); // Default deserialization
        age = in.readInt(); // Custom deserialization for transient field
    }

    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + "}";
    }
}

public class CustomSerializationExample {
    public static void main(String[] args) {
        Person person = new Person("Alice", 30);

        // Serialization
        try (FileOutputStream fileOut = new FileOutputStream("person.ser");
             ObjectOutputStream out = new ObjectOutputStream(fileOut)) {
            out.writeObject(person);
            System.out.println("Object serialized and saved to person.ser");
        } catch (IOException e) {
            e.printStackTrace();
        }

        // Deserialization
        try (FileInputStream fileIn = new FileInputStream("person.ser");
             ObjectInputStream in = new ObjectInputStream(fileIn)) {
            Person deserializedPerson = (Person) in.readObject();
            System.out.println("Object deserialized: " + deserializedPerson);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

5. Serialization with Inheritance

  • If a superclass is serializable, its subclasses are automatically serializable.
  • If a superclass is not serializable, its subclass can still be serialized, but the superclass fields will not be serialized.

Example:

import java.io.*;

class Address {
    private String city;
    private String state;

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

    @Override
    public String toString() {
        return "Address{city='" + city + "', state='" + state + "'}";
    }
}

class Employee extends Person implements Serializable {
    private String department;
    private Address address; // Address is not serializable

    public Employee(String name, int age, String department, Address address) {
        super(name, age);
        this.department = department;
        this.address = address;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + super.toString() + '\'' +
                ", department='" + department + '\'' +
                ", address=" + address +
                '}';
    }
}

public class SerializationInheritanceExample {
    public static void main(String[] args) {
        Address address = new Address("New York", "NY");
        Employee employee = new Employee("Alice", 30, "IT", address);

        // Serialization
        try (FileOutputStream fileOut = new FileOutputStream("employee.ser");
             ObjectOutputStream out = new ObjectOutputStream(fileOut)) {
            out.writeObject(employee);
            System.out.println("Object serialized and saved to employee.ser");
        } catch (IOException e) {
            e.printStackTrace();
        }

        // Deserialization
        try (FileInputStream fileIn = new FileInputStream("employee.ser");
             ObjectInputStream in = new ObjectInputStream(fileIn)) {
            Employee deserializedEmployee = (Employee) in.readObject();
            System.out.println("Object deserialized: " + deserializedEmployee);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

6. Externalizable Interface

  • The Externalizable interface provides more control over the serialization process than Serializable.
  • It requires implementing writeExternal and readExternal methods.

Example:

import java.io.*;

class Person implements Externalizable {
    private String name;
    private int age;

    public Person() {} // No-arg constructor required for Externalizable

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

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeObject(name);
        out.writeInt(age);
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        name = (String) in.readObject();
        age = in.readInt();
    }

    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + "}";
    }
}

public class ExternalizableExample {
    public static void main(String[] args) {
        Person person = new Person("Alice", 30);

        // Serialization
        try (FileOutputStream fileOut = new FileOutputStream("person.ser");
             ObjectOutputStream out = new ObjectOutputStream(fileOut)) {
            person.writeExternal(out);
            System.out.println("Object serialized and saved to person.ser");
        } catch (IOException e) {
            e.printStackTrace();
        }

        // Deserialization
        try (FileInputStream fileIn = new FileInputStream("person.ser");
             ObjectInputStream in = new ObjectInputStream(fileIn)) {
            Person deserializedPerson = new Person();
            deserializedPerson.readExternal(in);
            System.out.println("Object deserialized: " + deserializedPerson);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

By understanding serialization and deserialization, you can effectively save and restore object states in Java!

Leave a Reply

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