Middle+
How to change the default behavior of serialization and deserialization in Java?
sobes.tech AI
Answer from AI
To modify the default serialization and deserialization behavior, writeObject and readObject methods are used, as well as the Externalizable mechanism.
Using writeObject and readObject
A class implementing Serializable can declare these methods. JVM will call them during serialization and deserialization respectively.
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class MyCustomSerializable implements Serializable {
private String data;
private transient int sensitiveData; // this field will not be serialized by default
public MyCustomSerializable(String data, int sensitiveData) {
this.data = data;
this.sensitiveData = sensitiveData;
}
// Called during serialization
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject(); // serialize non-transient fields
out.writeInt(sensitiveData * 2); // serialize modified sensitiveData
}
// Called during deserialization
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject(); // deserialize non-transient fields
this.sensitiveData = in.readInt() / 2; // restore sensitiveData
}
// getters and setters
}
Using Externalizable
The Externalizable interface provides full control over serialization/deserialization. The class must implement writeExternal and readExternal.
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
public class MyExternalizable implements Externalizable {
private String publicData;
private int privateData; // all fields are serialized/deserialized manually
// No-arg constructor is required
public MyExternalizable() {
// empty constructor
}
public MyExternalizable(String publicData, int privateData) {
this.publicData = publicData;
this.privateData = privateData;
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeUTF(publicData); // manual serialization
out.writeInt(privateData); // manual serialization
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
this.publicData = in.readUTF(); // manual deserialization
this.privateData = in.readInt(); // manual deserialization
}
// getters and setters
}
Comparison
| Feature | Serializable + writeObject/readObject | Externalizable |
|---|---|---|
| Control | Partial (complement to default) | Full |
| Implementation complexity | Simpler for basic cases | More code for all fields |
| Performance | Usually lower | Can be higher with optimization |
| Version compatibility | Better JVM support | Manual version management |
transient fields |
Ignored by default | Must be handled manually |
| Constructor | No-arg constructor recommended | No-arg constructor required |