Object Serialization
Object Serialization in Java is a process used to convert Object into a
binary format which can be persisted into disk or database or sent over network to
any other running Java virtual machine. Serialization
is very important feature provided by java api.
There are many other java technologies (JMS,EJB,RMI) uses serialization by default .
Making instances of your classes serializable is one step process. You just need add the implements Serializable clause to your class declaration
You need not write any methods to implements serialization of your object. The serialization of instances of the class are handled implicitly by the defaultWriteObject
method of ObjectOutputStream
. This method automatically writes out everything required to reconstruct an instance of the class.
defaultWriteObject() is responsible for serializing below entity of the class object.
Values of all non-transient and non-static members,
members reference (instance variable that refer to other object ) .
Class signature
In this post , I am going to cover various scenario of the java serialization.
Java serialization in IS-A relationship
Suerclass is serialized but subclass is not serialized
Superclass is not serialized but subclass is serialized
Both Superclass and Subclass is serialized
Both superclass and subclass is not serialized
Java serialization in Has-A relationship
Java object containing non serialized object reference.
Java Object containing serializable object reference.
Non Serializable java objects containing serializable Object reference.
Superclass is serialized but subclass is not serialized
Rule : 1
If parent class is implementing Serializable interface than all its child becomes serializable automatically.
So no need to explicitly implement serializable interface in sub class.
Below is the example to understand this scenario.
Let us create two java class Account and sub class SavingAccount.
1: import java.io.Serializable;
2: public class Account implements Serializable{
3: private String name;
4: private int accountId;
5: private String accountType;
6: public Account(){
7: }
8: public Account(String name, int accountId, String accountType) {
9: //super();
10: this.name = name;
11: this.accountId = accountId;
12: this.accountType = accountType;
13: }
14: public String getName() {
15: return name;
16: }
17: public void setName(String name) {
18: this.name = name;
19: }
20: public int getAccountId() {
21: return accountId;
22: }
23: public void setAccountId(int accountId) {
24: this.accountId = accountId;
25: }
26: public String getAccountType() {
27: return accountType;
28: }
29: public void setAccountType(String accountType) {
30: this.accountType = accountType;
31: }
32: }
1: public class SavingAccount extends Account{
2: private int id;
3: private int amount;
4: private static final long serialVersionUID = 1L;
5: public SavingAccount(String name,int accountId,String accountType,int id,int amount){
6: super(name,accountId,accountType);
7: this.id = id;
8: this.amount = amount;
9: }
10: public int getId() {
11: return id;
12: }
13: public void setId(int id) {
14: this.id = id;
15: }
16: public int getAmount() {
17: return amount;
18: }
19: public void setAmount(int amount) {
20: this.amount = amount;
21: }
22: }
We are done now. Let us serialize and de-serialize this class.
SerializationISARelationTest.java
Run This code.
1: import java.io.FileOutputStream;
2: import java.io.IOException;
3: import java.io.ObjectOutputStream;
4: public class SerializationISARelationTest {
5: /**
6: * @param args
7: */
8: public static void main(String[] args) {
9: // TODO Auto-generated method stub
10: //Account account=new Account("Saving",100,"SalaryAccount");
11: SavingAccount sAccount=new SavingAccount("Saving",100,"SalaryAccount",123456,5000);
12: try
13: {
14: FileOutputStream fileOut =
15: new FileOutputStream("/account.ser");
16: ObjectOutputStream out = new ObjectOutputStream(fileOut);
17: out.writeObject(sAccount);
18: out.close();
19: fileOut.close();
20: System.out.printf("Serialized data is saved in the file :: /account.ser");
21: }catch(IOException exp)
22: {
23: exp.printStackTrace();
24: }
25: }
26: }
Run This code.
1: import java.io.FileInputStream;
2: import java.io.IOException;
3: import java.io.ObjectInputStream;
4: public class DeserializeISARelation {
5: /**
6: * @param args
7: */
8: public static void main(String[] args) {
9: // TODO Auto-generated method stub
10: Account account=null;
11: SavingAccount saveAccount=null;
12: try
13: {
14: FileInputStream fileIn = new FileInputStream("/account.ser");
15: ObjectInputStream in = new ObjectInputStream(fileIn);
16: saveAccount = (SavingAccount) in.readObject();
17: in.close();
18: fileIn.close();
19: }catch(IOException exp)
20: {
21: exp.printStackTrace();
22: return;
23: }catch(ClassNotFoundException c)
24: {
25: System.out.println("Employee class not found");
26: c.printStackTrace();
27: return;
28: }
29: System.out.println("**************************************************************************");
30: System.out.println("Deserialized Account details..");
31: System.out.println("Account Name: " + saveAccount.getName());
32: System.out.println("account Id: " + saveAccount.getAccountId());
33: System.out.println("Account type: " + saveAccount.getAccountType());
34: System.out.println("**************************************************************************");
35: System.out.println(" Saving Account Deserialization : ");
36: System.out.println("saving Account ID: " + saveAccount.getId());
37: System.out.println("Amount: " + saveAccount.getAmount());
38: System.out.println("**************************************************************************");
39: }
40: }
Output :
**************************************************************************
Deserialized Account details..
Account Name: Saving account
Id: 100
Account type: SalaryAccount
**************************************************************************
Saving Account Deserialization :
saving Account ID: 123456
Amount: 5000
**************************************************************************
Superclass is not serialized but subclass is serialized
.
Rule :1
If superclass is not serializable and subclass object is serialized then state of the member variable of subclass will be saved but not the superclass.
1: import java.io.Serializable;
2: public class Account {
3: private String name;
4: private int accountId;
5: private String accountType;
6: public Account(){
7: }
8: public Account(String name, int accountId, String accountType) {
9: //super();
10: this.name = name;
11: this.accountId = accountId;
12: this.accountType = accountType;
13: }
14: public String getName() {
15: return name;
16: }
17: public void setName(String name) {
18: this.name = name;
19: }
20: public int getAccountId() {
21: return accountId;
22: }
23: public void setAccountId(int accountId) {
24: this.accountId = accountId;
25: }
26: public String getAccountType() {
27: return accountType;
28: }
29: public void setAccountType(String accountType) {
30: this.accountType = accountType;
31: }
32: }
1: import java.io.IOException;
2: import java.io.NotSerializableException;
3: import java.io.ObjectInputStream;
4: import java.io.ObjectOutputStream;
5: import java.io.Serializable;
6: public class SavingAccount extends Account implements Serializable{
7: private int id;
8: private int amount;
9: private static final long serialVersionUID = 1L;
10: public SavingAccount(String name,int accountId,String accountType,int id,int amount){
11: super(name,accountId,accountType);
12: this.id = id;
13: this.amount = amount;
14: }
15: public int getId() {
16: return id;
17: }
18: public void setId(int id) {
19: this.id = id;
20: }
21: public int getAmount() {
22: return amount;
23: }
24: public void setAmount(int amount) {
25: this.amount = amount;
26: }
27: }
1: <pre style="font-family:arial;font-size:12px;border:1px dashed #CCCCCC;width:99%;height:auto;overflow:auto;background:#f0f0f0;;background-image:URL(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAuRc0LpWtx6wr76KNgUiyQNva6shuGgz9UT9pX2-XTU7ZveYllNkGNfFySfesdQJb2g501Z45l9dEJgn8jz4NBnknAg3vs3atxjs1A2RqRiMJ0xNMcdoNMYaNR74VHFo97ZbKtWjC5zcp/s320/codebg.gif);padding:0px;color:#000000;text-align:left;line-height:20px;"><code style="color:#000000;word-wrap:normal;">1: import java.io.IOException;
2: 2: import java.io.NotSerializableException;
3: 3: import java.io.ObjectInputStream;
4: 4: import java.io.ObjectOutputStream;
5: 5: import java.io.Serializable;
6: 6: public class SavingAccount extends Account implements Serializable{
7: 7: private int id;
8: 8: private int amount;
9: 9: private static final long serialVersionUID = 1L;
10: 10: public SavingAccount(String name,int accountId,String accountType,int id,int amount){
11: 11: super(name,accountId,accountType);
12: 12: this.id = id;
13: 13: this.amount = amount;
14: 14: }
15: 15: public int getId() {
16: 16: return id;
17: 17: }
18: 18: public void setId(int id) {
19: 19: this.id = id;
20: 20: }
21: 21: public int getAmount() {
22: 22: return amount;
23: 23: }
24: 24: public void setAmount(int amount) {
25: 25: this.amount = amount;
26: 26: }
27: 27: }
28: </code></pre>
1: import java.io.FileInputStream;
2: import java.io.IOException;
3: import java.io.ObjectInputStream;
4: public class DeserializeISARelation {
5: /**
6: * @param args
7: */
8: public static void main(String[] args) {
9: // TODO Auto-generated method stub
10: Account account=null;
11: SavingAccount saveAccount=null;
12: try
13: {
14: FileInputStream fileIn = new FileInputStream("/account.ser");
15: ObjectInputStream in = new ObjectInputStream(fileIn);
16: saveAccount = (SavingAccount) in.readObject();
17: in.close();
18: fileIn.close();
19: }catch(IOException exp)
20: {
21: exp.printStackTrace();
22: return;
23: }catch(ClassNotFoundException c)
24: {
25: System.out.println("Employee class not found");
26: c.printStackTrace();
27: return;
28: }
29: System.out.println("**************************************************************************");
30: System.out.println("Deserialized Account details..");
31: System.out.println("Account Name: " + saveAccount.getName());
32: System.out.println("account Id: " + saveAccount.getAccountId());
33: System.out.println("Account type: " + saveAccount.getAccountType());
34: System.out.println("**************************************************************************");
35: System.out.println(" Saving Account Deserialization : ");
36: System.out.println("saving Account ID: " + saveAccount.getId());
37: System.out.println("Amount: " + saveAccount.getAmount());
38: System.out.println("**************************************************************************");
39: }
40: }
Output of the member variable of superclass is default value. the value which was explicitly set before serialization is not reflected in superclass output .
Output :
**************************************************************************
Deserialized Account details..
Account Name: null
account Id: 0
Account type: null
**************************************************************************
Saving Account Deserialization :
saving Account ID: 123456
Amount: 5000
**************************************************************************
Both Superclass and Subclass is serialized
Rule 1
If both superclass and subclass is serialized then state of member variable of both the class will be saved.
Output :
**************************************************************************
Deserialized Account details.
Account Name: Saving
account Id: 100
Account type: SalaryAccount
**************************************************************************
Saving Account Deserialization :
saving Account ID: 123456
Amount: 5000
**************************************************************************
Both Superclass and Subclass is not serialized
Not Serializable exception will be thrown as shown below:-
java.io.NotSerializableException: com.java.serialization.SavingAccount
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.writeObject(Unknown Source)
at com.java.serialization.SerializationISARelationTest.main(SerializationISARelationTest.java:23)
Some
facts about Java serialization
Implicit caching
Default behavior for Java serialization is to serialize any
unique object just once. When you resend objects when their values changed.
Although the object had been sent again with new value,it still will have its original value previously stored due to
implicit caching to improve performance.
The ObjectOutputStream caches
instances that it sends over the. But in any case, you need to send latest
value streams in-between calls if you plan on using it to (re)send the same
object instance. Then use reset() method
public void reset() throws IOException
Reset will disregard the state of any objects already written
to the stream. The state is reset to be the same as a new ObjectOutputStream.
The current point in the stream is marked as reset so the corresponding ObjectInputStream
will be reset at the same point. Objects previously written to the stream will
not be refered to as already being in the stream. They will be written to the
stream again.
Versioning
Consequence of not specifying serialVersionUID in your
serialized class is that when you add or modify any field in class then already
serialized class will not be able to recover because serialVersionUID generated
for new class and for old serialized object will be different.
Java serialization process relies on correct serialVersionUID
for recovering state of serialized object and throws java.io.InvalidClassException
in case of erialVersionUID mismatch.
It is recommended that alway declare serialVersionUID
Static final long
serialVersionUID = 1L; // 1L is just an example!
Some Quick important points about serialization:-
- When you serialize an object, the serialization mechanism works by chaining up the inheritance hierarchy, saving the sate of each Serializable super-class in turn. When serialization reaches the first non-serializable super-class, the serialization stops.
- If member variables of a serializable object reference to a non-serializable object, the code will compile but a Runtime Exception NotSerializableException will be thrown.
- Static fields (with static modifier) are Not serialized.
- All primitive types are serializable.
- Transient fields (with transient modifier) are NOT serialized, (i.e., not saved or restored).A class that implements Serializable must mark -transient fields of classes that do not support serialization (e.g., a file stream).
- An object is serializable only if its class or its super-class implements the Serializable (or Externalizable) interface.
- An object is serializable (itself implements the Serializable interface) even if its superclass is not. However, the first superclass in the hierarchy of the serializable class, that does not implements Serializable interface, MUST have a no-arg constructor. If this is violated, readObject() will produce a java.io.InvalidClassException in runtime.
- The no-arg contructor of every non-serializable superclass will run when an object is deserialized. However, the deserialized objects? constructor does not run when it is deserialized.
- The class must be visible at the point of serialization.
Next Post we will
see serialization with HAS-A relationship.
Happy Reading..