Table of Contents
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:
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:
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:
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.
I build softwares that solve problems. I also love writing/documenting things I learn/want to learn.