Customizing serialization with Externalizable

With serialization, you can save the current state of an object to a stream and restore it back at a later point in time. With typical serialization, the fields are written using a default mechanism that specifies, for example, the order in which the fields are written. With making an object Externalizable and implementing the methods writeExternal and readExternal, you can do the serialization and restoration of the object yourself, including version checks.

The following example shows you how to customize serialization through the readExternal and writeExternal methods. It creates an object of type Test that contains a String and an integer array. It will only serialize the odd indexes of this array.

Main.java:

import java.io.*;
 
public class Main {
   public static void main(String args[]) {
      try {
         Test t = new Test("esus", new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });
         System.out.println("Serialize this object:");
         System.out.println(t);
 
         // create byte buffer containing serialized version of t 
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         ObjectOutputStream oos = new ObjectOutputStream(baos);
         t.writeExternal(oos);
         // very important to flush the stream, or you'll get java.io.EOFException
         oos.flush();            
         byte[] buffer = baos.toByteArray(); 
 
         Test t2 = new Test();
         ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(buffer));
         t2.readExternal(ois);      
      
         System.out.println("nDeserialization result:"); 
         System.out.println(t2);
      }
      catch(ClassNotFoundException e) { 
         System.out.println(e);
      }
      catch(IOException e) { 
         System.out.println(e);
      }
   }
}
 
class Test implements Externalizable {
   String s;
   int[] array;
  
   Test() { }
   Test(String s, int[] array) {
      this.s = s;
      this.array = array;
   }
 
   public void writeExternal(ObjectOutput out) throws IOException {
      out.writeObject(s);
      out.writeInt(array.length);
      for (int i=0; i<array.length; i+=2) {
         out.writeInt(i);
         out.writeInt(array[i]);
      }
   }
 
   public void readExternal(ObjectInput in) throws IOException, 
                                                   ClassNotFoundException {
      s = (String) in.readObject();
      int len = in.readInt();
      array = new int[len];
      for (int i=0; i<len/2; i++) {
         int index = in.readInt();
         array[index] = in.readInt();
      }
   }
 
   public String toString() {
      String total = "s = " + s + "; array = ";
      for (int i=0; i<array.length; i++) {
         total += array[i] + " ";
      }
      return total;
   }
}

outputs:

Serialize this object:
s = esus; array = 1 2 3 4 5 6 7 8 9 10
 
Deserialization result:
s = esus; array = 1 0 3 0 5 0 7 0 9 0