10.3 Externalizable Classes

The Externalizable interface extends Serializable and defines the writeExternal( ) and readExternal( ) methods. An Externalizable object may be serialized as other Serializable objects are, but the serialization mechanism calls writeExternal( ) and readExternal( ) to perform the serialization and deserialization. Unlike the readObject( ) and writeObject( ) methods in Example 10-2, the readExternal( ) and writeExternal( ) methods can't call the defaultReadObject( ) and defaultWriteObject( ) methods: they must read and write the complete state of the object by themselves.

It is useful to declare an object Externalizable when the object already has an existing file format or when you want to accomplish something that is simply not possible with the standard serialization methods. Example 10-3 defines the CompactIntList class, an Externalizable subclass of the IntList class of Example 2-7. CompactIntList makes the assumption that it is typically used to store small integers that fit in two bytes instead of four; it implements Externalizable so it can define a serialized form that is more compact than the format used by ObjectOutputStream and ObjectInputStream.

Example 10-3. CompactIntList.java
package je3.serialization; import je3.classes.IntList; import java.io.*; /**  * This subclass of IntList assumes that most of the integers it contains are  * less than 32,000.  It implements Externalizable so that it can define a   * compact serialization format that takes advantage of this fact.  **/ public class CompactIntList extends IntList implements Externalizable {     /**      * This version number is here in case a later revision of this class wants      * to modify the externalization format, but still retain compatibility      * with externalized objects written by this version      **/     static final byte version = 1;     /**      * This method from the Externalizable interface is responsible for saving      * the complete state of the object to the specified stream.  It can write      * anything it wants as long as readExternal( ) can read it.      **/     public void writeExternal(ObjectOutput out) throws IOException {         trim( );  // Compact the list to its current size         out.writeByte(version);  // Start with our version number.         out.writeInt(size);      // Output the number of array elements         for(int i = 0; i < size; i++) {  // Now loop through the array             int n = data[i];             // The array element to write             if ((n <= Short.MAX_VALUE) && (n > Short.MIN_VALUE)) {                 // If n fits in a short and is not Short.MIN_VALUE, then write                 // it out as a short, saving ourselves two bytes                 out.writeShort(n);             }             else {                 // Otherwise write out the special value Short.MIN_VALUE to                 // signal that the number does not fit in a short, and then                 // output the number using a full 4 bytes, for 6 bytes total                 out.writeShort(Short.MIN_VALUE);                 out.writeInt(n);             }         }     }     /**      * This Externalizable method is responsible for completely restoring the      * state of the object.  A no-arg constructor will be called to recreate      * the object, and this method must read the state written by       * writeExternal( ) to restore the object's state.      **/     public void readExternal(ObjectInput in)         throws IOException, ClassNotFoundException     {         // Start by reading and verifying the version number.         byte v = in.readByte( );         if (v != version)             throw new IOException("CompactIntList: unknown version number");         // Read the number of array elements, and make array that big         int newsize = in.readInt( );         setCapacity(newsize);  // A protected method inherited from IntList         this.size = newsize;   // Save this size.         // Now read that many values from the stream         for(int i = 0; i < newsize; i++) {             short n = in.readShort( );             if (n != Short.MIN_VALUE) data[i] = n;             else data[i] = in.readInt( );         }     }     /** A main( ) method to prove that it works */     public static void main(String[  ] args) throws Exception {         CompactIntList list = new CompactIntList( );         for(int i = 0; i < 100; i++) list.add((int)(Math.random( )*40000));         CompactIntList copy = (CompactIntList)Serializer.deepclone(list);         if (list.equals(copy)) System.out.println("equal copies");         Serializer.store(list, new File("compactintlist.ser"));     } }


Java Examples in a Nutshell
Java Examples in a Nutshell, 3rd Edition
ISBN: 0596006209
EAN: 2147483647
Year: 2003
Pages: 285

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net