In Records, serialization is not done the same way as for ordinary serializable or externalizable classes. The serialized representation of a
record object will be a sequence of values (record components). During the deserialization of records, the stream of components is read and components
are constructed. Then the record object is recreated by invoking the record’s canonical constructor with the component values serving as arguments (or
default values for absent arguments).
This process cannot be customized, so any class-specific writeObject
, readObject
, readObjectNoData
,
writeExternal
, and readExternal
methods or serialPersistentFields
fields in record classes are ignored during
serialization and deserialization.
However, there is a way to substitute serialized/deserialized objects in writeReplace
and readResolve
.
This rule raises an issue when any of writeObject
, readObject
, readObjectNoData
, writeExternal
,
readExternal
or serialPersistentFields
are present as members in a Record class.
Noncompliant code example
record Record() implements Serializable {
@Serial
private static final ObjectStreamField[] serialPersistentFields = new ObjectStreamField[0]; // Noncompliant
@Serial
private void writeObject(ObjectOutputStream out) throws IOException { // Noncompliant
...
}
}
record Record() implements Externalizable {
@Override
public void writeExternal(ObjectOutput out) throws IOException { // Noncompliant
...
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { // Noncompliant
...
}
}
Compliant solution
record Record() implements Serializable {}
record Record() implements Serializable {
private Object writeReplace() throws ObjectStreamException {
...
}
private Object readResolve() throws ObjectStreamException {
...
}
}