write invocations of these methods could have been replaced with a simple invocation of methods that
perform default serialization and deserialization:
private void writeObject(ObjectOutputStream out)
throws IOException
{
out.defaultWriteObject();
}
private void readObject(ObjectInputStream in)
throws IOException, ClassNotFoundException
{
in.defaultReadObject();
hash = name.hashCode();
}
In fact, as you may have surmised, given that writeObject performs nothing but default serialization, we
need not have implemented it at all.
A writeObject method can throw NotSerializableException if a particular object is not
serializable. For example, in rare cases, objects of a class might be generally serializable, but a particular
object might contain sensitive data.
You will occasionally find that an object cannot be initialized properly until the graph of which it is a part has
been completely deserialized. You can have the ObjectInputStream invoke a method of your own
devising by calling the stream's registerValidation method with a reference to an object that
implements the interface ObjectInputValidation. When deserialization of the top-level object at the
head of the graph is complete, your object's validateObject method will be invoked to make any needed
validation operation or check.
Normally, an object is serialized as itself on the output stream, and a copy of the same type is reconstituted
during deserialization. You will find a few classes for which this is not correct. For example, if you have a
class that has objects that are supposed to be unique in each virtual machine for each unique value (so that ==
will return TRue if and only if equals also would return true), you would need to resolve an object being
deserialized into an equivalent one in the local virtual machine. You can control these by providing
writeReplace and readResolve methods of the following forms and at an appropriate access level:
<access>ObjectwriteReplace()throws ObjectStreamException
Returns an object that will replace the current object during serialization. Any
object may be returned including the current one.
<access>ObjectreadResolve()tHRows ObjectStreamException
Returns an object that will replace the current object during deserialization.
Any object may be returned including the current one.
In our example, readResolve would check to find the local object that was equivalent to the one just
deserializedif it exists it will be returned, otherwise we can register the current object (for use by
readResolve in the future) and return this. These methods can be of any accessibility; they will be used
if they are accessible to the object type being serialized. For example, if a class has a private readResolve
method, it only affects deserialization of objects that are exactly of its type. A package-accessible
readResolve affects only subclasses within the same package, while public and protected readResolve
methods affect objects of all subclasses.