Object Streams – Serialization and Deserialization in Java example using Serializable Interface

In the previous java tutorials, we have discussed the basic of java streams, byte streams, then a modified version of them character streams which were specially for character data, then data streams to solve the problem of reading and writing java primitives directly and we will discuss Object Stream in details in this article and how to serialize and deserialize objects.

So lets start with the very basic question

1. What are Object Streams?

Object Streams are used to save the state to an object by converting it into a stream and storing into a file, database or some other location(known as Serialization) and to use it at a later point of time for retrieving the stored values and restoring the objects old state( known as Deserialization).

This serialization and deserialization helps us in many scenarios like gaming, session state management etc.

1.1. Real-life scenarios

Have you ever wondered how a game starts from the same point where we have left it? Then this is your answer. All this is done by saving the current state of the object(or game) and reloading the state so that the player could continue from the old state only. Also, the checkpoint system in games follows this method by permanently saving the progress up to that state for later use.

Serialization-deserialization in Java - Object Streams
Serialization-deserialization in Java – Object Streams

2. Marker Interface

An interface in Java without any field and method is a Marker interface. It is used to inform compiler that the class implementing it has some special behavior or meaning. Some of the Marker interfaces are-

  • java.io.Serializable
  • java.rmi.Remote
  • java.util.RandomAccess
  • java.lang.Cloneable

Although since Java 5 marker interfaces are replaced by annotations and they serve the same purpose as marker interfaces did before but for serializability we still use the interfaces and the transient keyword.

2.1 Interfaces

Every Object Stream class implements either of the two interfaces-

  1. ObjectInput – subinterface of DataInput
  2. ObjectOutput – subinterface of DataOutput

Note:- Since both the interfaces above are sub interface of interfaces Data streams interfaces, That means that all the primitive data I/O methods covered in Data Streams are also implemented in object streams.


3. Classes for Object Streams

Two classes that are used for Object Streams are –

3.1. ObjectInputStream

  1. This Java class is responsible for deserializing the previously serialized objects and the primitive data.
  2. It reads the object from the graph of objects stored while using FileInputStream.
  3. Method readObject() is the main method used to deserialize the object.The class of the object, the signature of the class, and the values of the non-transient and non-static fields of the class and all of its super types are read.
    • public final Object readObject() throws IOException,ClassNotFoundException

3.2. ObjectOutputStream

  1. This Java class is used to store primitives and a graph of Java objects which are available to ObjectInputStream to read data from.
  2. This does not care about saving the super class and sub-class data but it could be achieved by using the writeObject method or by using the methods for primitive data types supported by DataOutput.
  3. Method writeObject() is the main method of this Java class which serializes the object directly.
    • public final void writeObject(Object obj) throws IOException

4. Transient Keyword

There are scenarios in which we want to store only a part of the object i.e. we want to omit some specific fields from the stored object just like the password field from any user class or an Employee or you can think of any other sensitive information.

In these cases we mark these fields as transient and this keyword protects the field from being saved during the process of serialization.

Example – transient private String password;


5. Serialization and Deserialization Example

Now lets take an example and see how to do this using actual Java coding and have a look at some key points that should be remembered while using Serializable interface.

User.Java

package com.codingeek.serialization;

import java.io.Serializable;

public class User implements Serializable {

  /**
   * Generated Serial version Id
   */
  private static final long serialVersionUID = -55857686305273843L;

  private String name;
  private String username;
  transient private String password;

  @Override
  public String toString() {
    // TODO Auto-generated method stub
    String value = "name : " + name + "UserName : " + username + "Password : " + password;
    return value;
  }

  // getters and setters
}
  • Make sure that the Java class you need to store must implement Serializable interface.
  • Notice that the password field in the above class is made transient because it is a piece of sensitive information and we don’t want to store it or you can choose any other field.
  • Also, there is another field named serialVersionUID which is a Long variable and it should be defined for all the Java classes because if it is not and if in the future we need to perform any changes in the class like variables, methods, etc then we would never be able to deserialize an already serialized object.

You can try it yourself by first serializing the object and then do some changes in your java class before deserializing it. You will get an error stating the change in SerialVersionUID which is generated automatically by the compiler.

SerializationUtil.java

package com.codingeek.serialization;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

/**
 * This class is a utility class for performing the serialization and
 * deserialization operations provided the required information.
 *
 * @author hiteshgarg
 */
public class SerializationUtil {

  /**
   * deserialize to Object from given file. We use the general Object so as that
   * it can work for any Java Class.
   */
  public static Object deserialize(String fileName) throws IOException, ClassNotFoundException {
    FileInputStream fis = new FileInputStream(fileName);
    BufferedInputStream bis = new BufferedInputStream(fis);
    ObjectInputStream ois = new ObjectInputStream(bis);
    Object obj = ois.readObject();
    ois.close();
    return obj;
  }

  /**
   * serialize the given object and save it to given file
   */
  public static void serialize(Object obj, String fileName) throws IOException {
    FileOutputStream fos = new FileOutputStream(fileName);
    BufferedOutputStream bos = new BufferedOutputStream(fos);
    ObjectOutputStream oos = new ObjectOutputStream(bos);
    oos.writeObject(obj);
    oos.close();
  }
}

In the above Java utility class we have used

  • File Streams(For file related operations) which are wrapped in
  • Buffered Streams(for Speeding up the operations) which are finally wrapped into
  • Object Streams(for serialization and deserialization operations).

SerializationTest.java

package com.codingeek.serialization;

import java.io.IOException;

public class SerializationTest {

  public static void main(String[] args) {
    User user = new User();
    user.setName("Hitesh");
    user.setUsername("Codingeek");
    user.setPassword("Garg");

    try {
      /**
       * Serializing the object
       */
      SerializationUtil.serialize(user, "serialization.txt");

      /**
       * Deserializing the object
       */
      User newUser = (User) SerializationUtil.deserialize("serialization.txt");
      System.out.println(newUser.toString());

    } catch (IOException | ClassNotFoundException e) {
      e.printStackTrace();
    }
  }
}
Output:-
name : Hitesh
UserName : Codingeek
Password : 

Notice that the password value is null and it is because we have made it a transient field and hence it was not stored and at the time of deserialization a default value is assigned to this variable( which is obviously null).


An investment in knowledge always pays the best interest. I hope you like the tutorial. Do come back for more because learning paves way for a better understanding

Do not forget to share and Subscribe.

Happy coding!! 😊

Recommended -

Subscribe
Notify of
guest
10 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Yunxing Wang
6 years ago

very simple and useful
fos.close();
should be
oos.close();

hiteshgarg21
hiteshgarg21
6 years ago
Reply to  Yunxing Wang

Oh ya.. That was just a testing mistake. Thank you. corrections are done.

Neelima
Neelima
6 years ago

Very precise and easy to understand. Thanks

hiteshgarg21
hiteshgarg21
6 years ago
Reply to  Neelima

Thanks @neelima … It feels great to have such reviews and you guys motivate us a lot to keep writing such articles…

Iksem
Iksem
6 years ago

This is great! thank you

Reddy
Reddy
6 years ago

how to read multiple objects from the file….

Naveen
Naveen
6 years ago

Amazing explanation

Hareem Naz
Hareem Naz
6 years ago

nice tutorial 🙂

narendra kumar
narendra kumar
4 years ago

very very nice …………now i am seeing this website it is good opportunity for us to learn from this platform thank you for giving this type of knowledge

M Chandry
6 months ago

Hello,

Can you please expand on this example, to show how to input the object data into the file the same way as the toString() for that object?

10
0
Would love your thoughts, please comment.x
()
x