Declaring transient fields Implementing writeObject and readObject

• serialPersistentFields can be declared.

10.3.2.1 Declaring transient fields

The first, and easiest, thing you can do is simply mark some fields using the transient keyword. In ArrayList , for example, elementData is really declared to be a transient field: public class ArrayList extends AbstractList implements List, Cloneable, java.io. Serializable { private transient Object elementData[]; private int size; ... } This tells the default serialization mechanism to ignore the variable. In other words, the serialization mechanism simply skips over the transient variables. In the case of ArrayList , the default serialization mechanism would attempt to write out size , but ignore elementData entirely. This can be useful in two, usually distinct, situations: The variable isnt serializable If the variable isnt serializable, then the serialization mechanism will throw an exception when it tries to serialize the variable. To avoid this, you can declare the variable to be transient. The variable is redundant Suppose that the instance caches the result of a computation. Locally, we might want to store the result of the computation, in order to save some processor time. But when we send the object over the wire, we might worry more about consuming bandwidth and thus discard the cached computation since we can always regenerate it later on.

10.3.2.2 Implementing writeObject and readObject

Suppose that the first case applies. A field takes values that arent serializable. If the field is still an important part of the state of our instance, such as elementData in the case of an ArrayList , simply declaring the variable to be transient isnt good enough. We need to save and restore the state stored in the variable. This is done by implementing a pair of methods with the following signatures: private void writeObjectjava.io.ObjectOutputStream out throws IOException private void readObjectjava.io.ObjectInputStream in throws IOException, ClassNotFoundException; When the serialization mechanism starts to write out an object, it will check to see whether the class implements writeObject . If so, the serialization mechanism will not use the default mechanism and will not write out any of the instance variables. Instead, it will call writeObject and depend on the method to store out all the important state. Here is ArrayList s implementation of writeObject : private synchronized void writeObjectjava.io.ObjectOutputStream stream throws java. io.IOException { stream.defaultWriteObject ; stream.writeIntelementData.length; for int i=0; isize; i++ stream.writeObjectelementData[i]; } The first thing this does is call defaultWriteObject . defaultWriteObject invokes the default serialization mechanism, which serializes all the nontransient, nonstatic instance variables. Next, the method writes out elementData.length and then calls the streams writeObject for each element of elementData . Theres an important point here that is sometimes missed: readObject and writeObject are a pair of methods that need to be implemented together. If you do any customization of serialization inside one of these methods, you need to implement the other method. If you dont, the serialization algorithm will fail. Unit Tests and Serialization Unit tests are used to test a specific piece of functionality in a class. They are explicitly not end-to-end or application-level tests. Its often a good idea to adopt a unit-testing harness such as JUnit when developing an application. JUnit gives you an automated way to run unit tests on individual classes and is available from ht t p: w w w .j unit .or g . If you adopt a unit-testing methodology, then any serializable class should pass the following three tests: • If it implements readObject , it should implement writeObject , and vice-versa. • It is equal using the equals method to a serialized copy of itself. • It has the same hashcode as a serialized copy of itself. Similar constraints hold for classes that implement the Externalizable interface.

10.3.2.3 Declaring serialPersistentFields