Java Reference
In-Depth Information
If you do not want Java to share an object reference, use the
writeUnshared()
method instead of the
writeObject()
method of the
ObjectOutputStream
class to serialize an object. An object written using the
writeUnshared()
method is not shared or back referenced by any subsequent call to the
writeObject()
method
or the
writeUnshared()
method on the same object. You should read the object that was written using the
writeUnshared()
using the
readUnshared()
method of the
ObjectInputStream
class. If you replace the call to
writeObject()
with
writeUnshared()
and the call to
readObject()
with
readUnshared()
in
MutipleSerialization
class, you get the changed state of the object back when you read the object again.
You can control the serialization of a
Serializable
object in another way by defining a field named
serialPersistentFields
, which is an array of
ObjectStreamField
objects. This field must be declared
private
,
static
, and
final
. It declares that all the fields mentioned in this array are serializable. Note that this is just the
opposite of using the
transient
keyword with a field. When you use a
transient
keyword, you state that this field is
not serializable, whereas by declaring a
serialPersistentFields
array, you state that these fields are serializable.
The declaration of
serialPersistentFields
takes over the declaration of
transient
fields in a class. For example, if
you declare a field
transient
and include that field in the
serialPersistentFields
field, that field will be serialized.
The following snippet of code shows how to declare a
serialPersistentFields
field in a
Person
class:
class Person implements Serializable {
private String name;
private String gender;
private double height;
// Declare that only name and height fields are serializable
private static final ObjectStreamField[] serialPersistentFields
= {new ObjectStreamField("name", String.class),
new ObjectStreamField("height", double.class)};
}
Class Evolution and Object Serialization
Your class may evolve (or change) over time. For example, you may remove an existing field or a method from a class.
You may add new fields or methods to a class. During an object serialization, Java uses a number that is unique for
the class of the object you serialize. This unique number is called the
serial version unique ID
(SUID). Java computes
this number by computing the hash code of the class definition. If you change the class definition such as by adding
new fields, the SUID for the class will change. When you serialize an object, Java also saves the class information to
the stream. When you deserialize the object, Java computes the SUID for the class of the object being deserialized by
reading the class definition from the stream. It compares the SUID computed from the stream with the SUID of the
class loaded into the JVM. If you change the definition of the class after you serialize an object of that class, the two
numbers will not match and you will get a
java.io.InvalidClassException
during the deserialization process. If
you never serialize the objects of your class or you never change your class definition after you serialize the objects
and before you deserialize them, you do not need to worry about the SUID of your class. What should you do to make
your objects deserialize properly, even if you change your class definition, after serializing objects of your class? You
should declare a
private
,
static
, and
final
instance variable in your class that must be of the long type and named
serialVersionUID
.
public class MyClass {
// Declare the SUID field. L in "801890L" denotes a long value
private static final long serialVersionUID = 801890L;
// More code goes here
}