As you know serialization is general technique or process to store in-memory objects into some persistent format. For doing this Java provides interface and classes, by using these you can serialize and de-serialize object very easily.
Serializable
marker Interface ObjectInputStream
and ObjectOutputStream
main things which you have to use to do serialization and de-serialization in Java.
So let’s start with one simple example, we have one UserInfo
class has three fields and one of the field is marked transient
.
Class which i want to serialize
public class UserInfo { private String user; private transient String password; private int id; public String getUser() { return user; } public void setUser(String user) { this.user = user; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String toString() { return "user:" + user + " password: " + password + " email: " + id; } }
For serializing any object we need to write that object into ObjectOutputStream.writeObject(Object object)
method. Obviously first you need to associate ObjectOutputStream
with some OutputStream
where you want to store objects.
For de-serializing any object we need to read object from Object ObjectInputStream.readObject()
method. Obviously first you need to associate ObjectInputStream
with some InputStream
from where you want to read object.
Code to serialize and de-serialize object into file
public class Test { public static void main(String[] args) { UserInfo userInfo = new UserInfo(); userInfo.setUser("Anupama"); userInfo.setPassword("password"); userInfo.setId(1001); serialize(userInfo); userInfo = (UserInfo) deserialize(); System.out.println("After desialization using Serializable"); System.out.println(userInfo); } private static void serialize(Object obj) { try { FileOutputStream fileOut = new FileOutputStream("userinfo.ser"); ObjectOutputStream out = new ObjectOutputStream(fileOut); out.writeObject(obj); out.close(); fileOut.close(); System.out.println(obj); System.out.println("Serialized data is saved in userinfo.ser"); } catch (IOException i) { i.printStackTrace(); } } private static Object deserialize() { Object obj = null; try { FileInputStream fileIn = new FileInputStream("userinfo.ser"); ObjectInputStream in = new ObjectInputStream(fileIn); obj = in.readObject(); in.close(); fileIn.close(); } catch (IOException i) { i.printStackTrace(); return null; } catch (ClassNotFoundException c) { System.out.println("UserInfo class not found"); c.printStackTrace(); return null; } return obj; }
In above code in created object of UserInfo
class and set values to files and tried to serialize it but it throw an exception java.io.NotSerializableException
at out.writeObject(obj);
. This exception is because of i did\’t use Serializable
marker interface in UserInfo
class. Serializable
marker interface is used to tell ObjectOutputStream
that this class can be serialized as ObjectOutputStream
check given object is design to serialize or not as in many cases some developer don\’t want that any one can serialize it\’s complete class and for this there can be many reasons like what kind of private variables he used to impletent his class.
So it is clear that for serializing any object using ObjectOutputStream
object must implement Serializable
marker interface as other serialization interface like Externalizable
extends Serializable
.
Now implement Serializable
marker inteface UserInfo
class and try to serialize
public class UserInfo implements Serializable{ ... }
It will give following output
user:Anupama password: password email: 1001 Serialized data is saved in userinfo.ser After desialization using Serializable user:Anupama password: null email: 1001
In above output you can see after deserialization password is null, this is because i marked password field in UserInfo
class transient
. This is to indicate ObjectOutputStream
class that do not serialize fields which are marked transient
.
So till now it clear that it will serialize all fields of class public
, protected
, private
and not transient
, what about static fields?
What is behavior of constructor?
There is no role of constructors at the time of serialization and deserialization when serializing using default serialization method provided by java. Note in case base class is not marked Serializable
then default constructor of base class will be call at the time of de-serialization.
What is behavior of final fields?
Final fields are treated normal fields.
Try to find out what happens to static fields
Create a new class Statics
as given below
public class Statics implements Serializable { public static int VALUE1= 10; public static int VALUE2= 20; public String toString() { return "VALUE1: "+VALUE1+" VALUE2: "+ VALUE2; } }
Now test it using following code in above main function
public static void main(String[] args) { Statics statics = new Statics(); serialize(statics); // Change static values Statics.VALUE1 = 100; Statics.VALUE2 = 200; // de-serialize old value statics = (Statics) deserialize(); System.out.println("After desialization using Serializable"); System.out.println(statics); }
Below is output
VALUE1: 10 VALUE2: 20 Serialized data is saved in statics.ser After desialization using Serializable VALUE1: 100 VALUE2: 200
After seeing above output it is clear that ObjectOutputStream
never serialize static or static final by default for Serializable
type objects
Inheritance and Serialization
If base class is not marked Serializable
then field of base class will not serialize and during de-serialization it will invoke default constructor of base classes and desterilize on classes marked Serializable
.