Sunday, December 2, 2012

Customizing Serialization in JAVA

Take a look at this program. If I try to compile this, the compiler will throw NoSerializableException.
public class Unicycle implements Serializable {

 private static final long serialVersionUID = 3843396491741625744L;

 private Wheel wheel;
 
 public Unicycle( Wheel wheel ) { 
  this.wheel = wheel; 
 }
 
 public String toString() {
  return "Unicycle with " + wheel;
 }
}

public class Wheel {

 private static final long serialVersionUID = -8786651610841969855L;

 private int wheelSize;
 
 public Wheel( int ws ) { 
  wheelSize = ws; 
 }
 
 public String toString() { 
  return "wheel size: " + wheelSize; 
 }
}

public class Main {

 public static void main(String args[]) throws IOException, ClassNotFoundException {

  Main main = new Main();
  
  main.writeData();
  main.readData();
 }
 
 public void writeData() throws IOException {
  
  FileOutputStream outputFile = new FileOutputStream("storage.dat");
  ObjectOutputStream outputStream = new ObjectOutputStream(outputFile);
  
  Wheel wheel = new Wheel(65);
  Unicycle uc = new Unicycle(wheel);
  
  System.out.println("Before writing: " + uc);
  
  outputStream.writeObject(uc);
  outputStream.flush();
  outputStream.close();
 }
 
 public void readData() throws IOException, ClassNotFoundException {
  
  FileInputStream inputFile = new FileInputStream("storage.dat");
  ObjectInputStream inputStream = new ObjectInputStream(inputFile);
  
  Unicycle uc = (Unicycle) inputStream.readObject();
  
  System.out.println("After reading: " + uc);
  
  inputStream.close();
 }

}

Perform 2 tasks in order to get this fix:
  1. The Wheel class has to be declared as transient in Unicycle class. (Note)
  2. Implement private void writeObject(ObjectOutputStream) and private void readObject(ObjectInputStream) in Unicycle class.
Note that these 2 methods isn't part of any interface, and accessible by the JVM even though it is declared as private. Below is the sample code of Unicycle class that implement these 2 methods:
public class Unicycle implements Serializable {
 ...

 transient private Wheel wheel;

 private void writeObject(ObjectOutputStream oos) {
  try {
   oos.defaultWriteObject();
   oos.writeInt(wheel.getWheelSize());
  }
  catch( IOException e ) {
   e.printStackTrace();
  }
 }
 
 private void readObject(ObjectInputStream ois) {
  try {
   ois.defaultReadObject();
   int wheelSize = ois.readInt();
   wheel = new Wheel(wheelSize);
  }
  catch( IOException e ) {
   e.printStackTrace();
  }
  catch( ClassNotFoundException e ) {
   e.printStackTrace();
  }
 }
}

This is what JAVA called Customizing Serialization.

No comments: