Detailed Explanation of Serialization and Deserialization Mechanisms in Java
I. Basic Concepts of Serialization
Serialization is the process of converting a Java object into a byte sequence, while deserialization is the process of restoring a Java object from a byte sequence. This mechanism allows objects to exist independently of the program, facilitating network transmission or persistent storage.
II. Implementation Methods of Serialization
- Implement the Serializable interface (a marker interface)
public class User implements Serializable {
private String name;
private int age;
// A no-argument constructor must be provided
public User() {}
// getter/setter methods
}
- Implement the Externalizable interface (requires overriding methods)
public class User implements Externalizable {
private String name;
private int age;
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeUTF(name); // Custom serialization logic
}
@Override
public void readExternal(ObjectInput in) throws IOException {
this.name = in.readUTF(); // Custom deserialization logic
}
}
III. Specific Steps of Serialization
- Create an object output stream:
User user = new User("Zhang San", 25);
try (ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("user.dat"))) {
oos.writeObject(user); // Perform serialization
}
- Detailed explanation of the serialization process:
- Check if the object implements the Serializable interface
- Use reflection to obtain all fields of the object
- Recursively serialize all referenced objects
- Convert object data into a byte stream and write it to the output source
IV. Specific Steps of Deserialization
- Create an object input stream:
try (ObjectInputStream ois = new ObjectInputStream(
new FileInputStream("user.dat"))) {
User user = (User) ois.readObject(); // Perform deserialization
}
- Detailed explanation of the deserialization process:
- Read the byte stream and parse metadata
- Use reflection to invoke the no-argument constructor to create an empty object
- Recursively deserialize all field values
- Restore the complete state of the object
V. Role of serialVersionUID
- A version control identifier used to verify the compatibility of serialized objects
- Correct way to declare it explicitly:
private static final long serialVersionUID = 1L;
- If not explicitly declared, the JVM will automatically generate it based on the class structure. Changes to the class structure may cause deserialization to fail.
VI. Custom Serialization Strategies
- Use the transient keyword to ignore fields:
private transient String password; // Will not be serialized
- Override the writeObject/readObject methods:
private void writeObject(ObjectOutputStream oos)
throws IOException {
oos.defaultWriteObject(); // Default serialization
oos.writeUTF(encrypt(password)); // Custom processing
}
private void readObject(ObjectInputStream ois)
throws IOException, ClassNotFoundException {
ois.defaultReadObject(); // Default deserialization
this.password = decrypt(ois.readUTF()); // Custom processing
}
VII. Notes on Serialization
- Static variables are not serialized (they belong to the class level)
- Parent class serialization rules:
- If the parent class implements Serializable: the child class is automatically serializable
- If the parent class does not implement it: a no-argument constructor is required, and parent class fields will not be serialized
- Serialization issues with inner classes: it is recommended to use static inner classes
VIII. Practical Application Scenarios
- Object network transmission (RPC calls)
- Object persistent storage
- Distributed cache storage
- Deep copy implementation solutions
By understanding these details, you can avoid common serialization pitfalls and flexibly customize serialization strategies based on business requirements.