Principle
/**
* @ Author Kaibo Hao Immutable class that uses defensive copying
*/
Public final class Period implements Serializable {
Private Date start;
Private Date end;
/**
* @ Param start
* The beginning of the period
* @ Param end
* The end of the period; must not precede start
* @ Throws IllegalArgumentException
* If start is after end
* @ Throws NullPointerException
* If start or end is null
*/
Public Period (Date start, Date end ){
This. start = new Date (start. getTime ());
This. end = new Date (end. getTime ());
If (this. start. compareTo (this. end)> 0)
Throw new IllegalArgumentException (start + "after" + end );
}
Public Date start (){
Return new Date (start. getTime ());
}
Public Date end (){
Return new Date (end. getTime ());
}
Public String toString (){
Return start + "-" + end;
}
// Remainder omitted
// ReadObject method with defensive copying and validity checking
Private void readObject (ObjectInputStream s) throws IOException,
ClassNotFoundException {
S. defaultReadObject ();
// Defensively copy our mutable components
Start = new Date (start. getTime ());
End = new Date (end. getTime ());
// Check that our invariants are satisfied
If (start. compareTo (end)> 0)
Throw new InvalidObjectException (start + "after" + end );
}
}
Guidelines for writing a bulletproof readObject method
Summary
Anytime you write a readObject method, adopt the mind-set that you are writing a public constructor that must produce a valid instance regardless of what byte stream it is given. do not assume that the byte stream represents an actual serialized instance.