A class that implements java.io.Externalizable
is a class that provides a way to customize the serialization and deserialization,
allowing greater control over how the object’s state is written or read.
The first step of the deserialization process is to call the class' no-argument constructor before the readExternal(ObjectInput in)
method.
An implicit default no-argument constructor exists on a class when no constructor is explicitly defined within the class. But this implicit constructor does not exist when any constructor is explicitly defined, and in this case, we should always ensure that one of the constructors has no-argument.
It is an issue if the implicit or explicit no-argument constructor is missing or not public, because the deserialization will fail and throw an
InvalidClassException: no valid constructor.
.
This issue can be fixed by:
public class Tomato implements Externalizable { public Color color; // Noncompliant; because of this constructor there is no implicit no-argument constructor, // deserialization will fail public Tomato(Color color) { this.color = color; } @Override public void writeExternal(ObjectOutput out) throws IOException { out.writeUTF(color.name()); } @Override public void readExternal(ObjectInput in) throws IOException { color = Color.valueOf(in.readUTF()); } }
public class Tomato implements Externalizable { public Color color; // Compliant; deserialization will invoke this public no-argument constructor public Tomato() { this.color = Color.UNKNOWN; } public Tomato(Color color) { this.color = color; } @Override public void writeExternal(ObjectOutput out) throws IOException { out.writeUTF(color.name()); } @Override public void readExternal(ObjectInput in) throws IOException { color = Color.valueOf(in.readUTF()); } }