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:
- Implement the
Serializable
interface. - 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:
- Use
ObjectInputStream
to read the object from a file or input stream. - 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
andreadObject
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 thanSerializable
. - It requires implementing
writeExternal
andreadExternal
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!