Java Serialization examples

What is serialization/deserialization?

Serialization is the process of converting objects to binary data.

Deserialization is the reversed process.

Java Serialization examples

Let’s consider some quick examples to get a basic understanding of Java serialization.

Writing objects to file

In this example, I will create an object and write the data into a file.

public class Basic {
    public static void main(String[] args) throws IOException, ClassNotFoundException, ClassCastException {
        try (FileOutputStream outputStream = new FileOutputStream("C:\\Users\\myn\\Downloads\\basic");
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);) {

            var list1 = List.of("Nice", "String");
            objectOutputStream.writeObject(list1);
        }
    }
}

Here, you can see that I created a list of String containing two elements. I used ObjectOutputStream to write the list to a file through a FileOutputStream instance.

If I open the file in a text editor (Notepad++) in this case, here is the content:

Open serialized file in a text editor
Open serialized file in a text editor

As you can see, some of the text is not readable. This is because the data was written in binary.

Now, let’s try to load the data from the file.

Reading objects from file

Reading data from a file and using deserialization in Java is quite simple. I only need to write these lines:

public class Basic {
    public static void main(String[] args) throws IOException, ClassNotFoundException, ClassCastException {
        try (FileInputStream fileInputStream= new FileInputStream("C:\\Users\\myn\\Downloads\\basic");
             ObjectInputStream  objectInputStream= new ObjectInputStream(fileInputStream);) {

            var list1 = (List<String>)objectInputStream.readObject();

            System.out.println(list1);
        }

    }
}

As you can see here, I opened a FileInputStream on the same file created before and use casting to cast the object to a List of String. Finally, I printed out the list and here is the result:

Deserialize binary data to object
Deserialize binary data to object

Serialization of shared object

You may wonder the case of a shared object. What’s the behavior of the shared object after serialization/deserialization?

Let’s find out.

Consider the following scenario, two cars share the same engine. It may not sound practical but it serves this example well.

The Car class:

public class Car implements Serializable {
    private Engine engine;
    public Car() {

    }

    public void setEngine(Engine engine) {
        this.engine = engine;
    }

    public Engine getEngine() {
        return engine;
    }

}

The Engine class

public class Engine implements Serializable {
    public Engine() {

    }
    private int hp;

    public int getHp() {
        return hp;
    }

    public void setHp(int hp) {
        this.hp = hp;
    }
}

Shared object example

public class NestedSerialization {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Engine engine = new Engine();
        engine.setHp(100);
        Car car1 = new Car();
        Car car2 = new Car();

        car1.setEngine(engine);
        car2.setEngine(engine);
        var cars = new Car[] { car1, car2 };

		//serialize objects to binary file
        serializeObject(car1, "car1");
        serializeObject(car2, "car2");
        serializeObject(cars, "cars");


       //deserialize binary data to objects
        var car11 = (Car) deserializeObject("car1");
        var car22 = (Car) deserializeObject("car2");
        var carsArray = (Car[]) deserializeObject("cars");

        car11.getEngine().setHp(300);

        System.out.println(car22.getEngine().getHp());//print 100

        carsArray[0].getEngine().setHp(400);
        System.out.println(carsArray[1].getEngine().getHp());//print 400
    }

    private static void serializeObject(Object object, String name) throws IOException {

        try (FileOutputStream outputStream = new FileOutputStream("C:\\Users\\myn\\Downloads\\" + name);
             ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);) {

            objectOutputStream.writeObject(object);
        }
    }

    private static Object deserializeObject(String name) throws IOException, ClassNotFoundException {
        try (FileInputStream fileInputStream = new FileInputStream("C:\\Users\\myn\\Downloads\\" + name);
             ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);) {

            return objectInputStream.readObject();
        }
    }

}

In this example, I did the following:

  • Created the Car and Engine classes. In the Car class, there is an Engine.
  • In the shared object example, I created two instances of cars: car1 and car2, both share a single engine that has HP (horsepower) set to 100.
  • Next, I called the serializeObject method to serialize the objects to files
  • Then I deserialized the binary data to Car objects and changed car11 engine’s HP to 300.
  • Finally, I printed out car22’s engine’s HP

Here is the result:

Serialization & Deserialization of shared object
Serialization & Deserialization of shared object

As you can see, the HP’s of car22 was 100, not 300. That means each car now has its own engine. The common instance is not shared anymore.

I can confirm this by running the code in debug mode:

As you can see, before serialization, car1 and car2 shared the same engine object. After serialization and deserialization, car22 and car11 have different Engine instances.

However, notice the carsArray. There are two cars in that array and they share the same engine instance.

This is because when serializing objects, the JVM assigns each object a serial number. Multiple occurrences of the same object are stored as references to such serial numbers.

Conclusion

This is a quick introduction to Java serialization/deserialization with some examples. In the next posts of this series, I’m going to dive deeper into this feature.

Leave a Comment