How to Control Serialization

Writing objects to a file that is possibly passed on to a third party before being read back in does mean a loss of control, which may cause concern for sensitive data. Of course, if we
do not want an object to be serialized at all, we simply do not include the implements Serializable clause in the class declaration. If, however, we do not want individual member variables to be serialized, while allowing the serialization of others, we can use the transient keyword. For example, if we do not want to allow serialization of the account name, we change line 5 of Account to

transient String accountName;

If we now run WriteAccount, then ReadAccount, acc1.accountName and acc2.accountName will both be set to null. The effect would have been the same if accountName had been a static variable.

We may want to act defensively and guard against our file being corrupted. For example, recall that the Account class constructor will throw a ValueTooSmallException if an attempt is made to create an Account object with a negative balance. The readObject method (in lines 9–10 of ReadAccount) does not invoke the Account constructor. So if the acc.dat file became corrupted and the balance of account1 altered from 40.0 to –40.0, ReadAccount would still create an acc1 object with a balance of –40.0 violating our constructor constraint. To guard against this, we can add our own version of the readObject method to the Account class.

readObject

private void readObject(ObjectInputStream in) throws
IOException, ClassNotFoundException
{
in.defaultReadObject();
if (balance < 0) {
throw new InvalidObjectException(''Negative Balance");
}
}


The first statement must be a call of the ObjectInputStream defaultReadObject method (line 3), which reads the nonstatic, nontransient variables of the current class, Account, from the stream. defaultReadObject throws IOException and ClassNotFoundException, so these should be included in the throws clause of the declaration (lines 1–2). Any customized code follows the defaultReadObject call. In this case, we throw an InvalidObjectException if the balance is negative (lines 4–6).An InvalidObjectException is used to indicate that one or more deserialized objects

have failed validation tests. As a defensive programming strategy, we would include all class constructor constraints in a readObject method if the class is being serialized.

In a similar manner, if we wish to customize the serialization process, we can add a writeObject method with customized code following a call to defaultWriteObject.

No comments:

Post a Comment