Recent Posts

Tuesday, 23 August 2016

File I/O & Serialization Tutorial Part 3



Inheritance in Serialization
      If the parent class is Serializable bydefault all the child classes also Serializable. i.e Serializable nature is inherited from parent to child.
       Hence even though child class doesn't implements Serializable , we can serialize child class bject if parent class implements serializable interface.
E.g
package com.ashok.files;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

class Animal implements Serializable {
   int a = 10;
}

class Dog extends Animal {
   int b = 20;
}

public class MySerialization {
   public static void main(String arg[]) throws Exception {
      Dog d = new Dog();
      FileOutputStream fos = new FileOutputStream("ashok.ser");
      ObjectOutputStream oos = new ObjectOutputStream(fos);
      oos.writeObject(d);
      FileInputStream fis = new FileInputStream("ashok.ser");
      ObjectInputStream ois = new ObjectInputStream(fis);
      Dog d1 = (Dog) ois.readObject();
      System.out.println(d1.a + " ----- " + d1.b);
   }
}
Output
10 ----- 20
     If the child class is Serializable and some of the parent classes are not Serializable, Still we are allowed to serialize child class Objects. While performing serialization JVM ignores the inherited variables which are coming from non-serializable parents. While performing de-serialization JVM will check is there any parent class is non-serializable or not.

     If any parent is non-serializable JVM will create an object for every non-serializable parent and share it’s instance variables for the current child object. The non-serializable parent class should compulsory contain no-argument constructor other wise we will get runtime error.
E.g
package com.ashok.files;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

class Animal {
   int i = 10;

   Animal() {
      System.out.println("Animal Constructor");
   }
}

class Dog extends Animal implements Serializable {
   int j = 20;

   Dog() {
      System.out.println("Dog Constructor");
   }
}

public class MySerialization {
   public static void main(String arg[]) throws Exception {
      Dog d = new Dog();
      d.i = 888;
      d.j = 999;
      System.out.println(d.i + "-----" + d.j);
      System.out.println("Serilization Started");
      FileOutputStream fos = new FileOutputStream("ashok.ser");
      ObjectOutputStream oos = new ObjectOutputStream(fos);
      oos.writeObject(d);
      System.out.println("Deserialization Started");
      FileInputStream fis = new FileInputStream("ashok.ser");
      ObjectInputStream ois = new ObjectInputStream(fis);
      Dog d1 = (Dog) ois.readObject();
      System.out.println(d1.i + "-----" + d1.j);
   }
}
Output
Animal Constructor
Dog Constructor
888-----999
Serilization Started
Deserialization Started
Animal Constructor
10-----999
Externalization
1. In default serialization every thing takes care by JVM and programmer doesn't have any control.

2. In serialization total object will be saved always and it is not possible to save part of the object , which creates performence problems at certain point.

3. To overcome these problems we should go for externalization where every thing takes care by programmer and JVM doesn't have any control.

4. The main advantage of externalization over serialization is we can save either total object or part of the object based on our requirement.

5. To provide Externalizable ability for any object compulsory the corresponding class should implements externalizable interface.

6. Externalizable interface is child interface of serializable interface.
Externalizable interface defines 2 methods
1. writeExternal( )
2. readExternal( )

public void writeExternal(ObjectOutput out) throws IOException
     This method will be executed automaticcay at the time of Serialization with in this method , we have to write code to save required variables to the file .

public void readExternal(ObjectInput in) throws IOException , ClassNotFoundException
     This method will be executed automatically at the time of deserialization with in this method , we have to write code to save read required variable from file and assign to the current object

     At the time of deserialization Jvm will create a seperate new object by executing public no-arg constructor on that object JVM will call readExternal() method.

     Every Externalizable class should compusory contains public no-arg constructor otherwise we will get RuntimeExcepion saying "InvaidClassException".
E.g
package com.ashok.files;

import java.io.Externalizable;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;

class MyExternal implements Externalizable {
   String s;
   int i;
   int j;

   public MyExternal() {
      System.out.println("Inside Constructor");
   }

   public MyExternal(String s, int i, int j) {
      this.s = s;
      this.i = i;
      this.j = j;
   }

   public void writeExternal(ObjectOutput out) throws IOException {
      out.writeObject(s);
      out.writeInt(i);
   }

   public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
      s = (String) in.readObject();
      i = in.readInt();
   }
}

public class MyExternalizable {
   public static void main(String[] args) throws Exception {
      MyExternal external = new MyExternal("Waytoeasylearn", 10, 20);
      FileOutputStream fos = new FileOutputStream("ashok.ser");
      ObjectOutputStream oos = new ObjectOutputStream(fos);
      oos.writeObject(external);

      FileInputStream fis = new FileInputStream("ashok.ser");
      ObjectInputStream ois = new ObjectInputStream(fis);
      MyExternal t2 = (MyExternal) ois.readObject();
      System.out.println(t2.s + ", " + t2.i + ", " + t2.j);
   }
}
Output
Inside Constructor
Waytoeasylearn, 10, 0
1. If the class implements Externalizable interface then only part of the object will be saved in the case output is
Inside Constructor
Waytoeasylearn, 10, 0

2. If the class implements Serializable interface then the output is Waytoeasylearn, 10, 20

3. In externalization transient keyword won't play any role , hence transient keyword not required.

Difference between Serialization & Externalization


serialVersionUID
1. To perform Serialization & Deserialization internally JVM will use a unique identifier , which is nothing but serialVersionUID .

2. At the time of serialization JVM will save serialVersionUID with object.

3. At the time of Deserialization JVM will compare serialVersionUID and if it is matched then only object will be Deserialized otherwise we will get RuntimeException saying "InvalidClassException".

The process in depending on default serialVersionUID are
1. After Serializing object if we change the .class file then we can't perform deserialization because of mismatch in serialVersionUID of local class and serialized object in this case at the time of Deserialization we will get RuntimeException saying in "InvalidClassException".

2. Both sender and receiver should use the same version of JVM if there any incompatability in JVM versions then receive anable to deserializable because of different serialVersionUID , in this case receiver will get RuntimeException saying "InvalidClassException" .

3. To generate serialVersionUID internally JVM will use complexAlgorithm which may create performence problems.

     We can solve above problems by configuring our own serialVersionUID. We can configure serialVersionUID as follows
private static final long serialVersionUID = 1L;
E.g
class Dog implements Serializable {
   private  static final  long  serialVersionUID=1L;
   int i=10;
   int j=20;
}
class Sender {
   public static void main(String[] args) throws Exception {
      Dog d1=new Dog();
      FileOutputStream fos=new FileOutputStream("abc.ser");
      ObjectOutputStream oos= new ObjectOutputStream(fos);
      oos.writeObject(d1);
   } 
}
class Receiver {
   public static void main(String[] args)throws Exception {
      FileInputStream fis=new FileInputStream("abc.ser");
      ObjectInputStream ois=new ObjectInputStream(fis);
      Dog d2=(Dog) ois.readObject();
      System.out.println(d2.i+"-----"+d2.j);  
   }
}
     In the above program after serialization even though if we perform any change to Dog.class file , we can deserialize object. We if configure our own serialVersionUID both sender and receiver not required to maintain the same JVM versions.

Note
     Some IDE's generate explicit serialVersionUID.

Next Tutorial  Garbage Collection Tutorial

Previous Tutorial  File I/O & Serialization Tutorial Part 2

No comments:

Post a Comment