In this post, we are going to explore an important Java concept frequently asked during Job’s interviews i.e. Java Serialization. We’ll exclusively talk about serialization and will explain its basic to advance level features with the help of code examples and sample project. Besides knowing about serialization in Java and it’s even more important to learn the different ways to implement serialization. We’ve also addressed them in this post. You probably have faced questions like does serialization require versioning or have performance issues? So, read this post through the end, we’ve covered all such questions. First of all, go over this generic definition of serialization.

“It is a way of converting data structures or state of the object in a format that can be preserved and retrieved as and when required. The process of reforming the object from the decomposed state is called deserialization. Today most of the object-oriented languages (including Java) provide native support for serialization and deserialization.”

Now you can see in the next section is the list of most basic Java serialization questions and answers. It’ll surely increase your knowledge of Java serialization topic.

1- Basics of Java Serialization.

1.1- What is the concept of Java serialization?

Answer: Java serialization is the process of turning an object into a stream of bytes or byte array. The byte array represents the class of the object, the version of the object, and the internal state of the object.

1.2- What is deserialization in Java?

Answer: Deserialization is the process of rebuilding byte stream into a live Java Object that must be usable.

1.3- What is the purpose of Java Serialization?

Answer: You can use Java serialization to perform the following tasks.

1.3.1- Stashing.

Rather holding a large object in memory, it’s better to cache it to a local file via serialization. For your note, if you attempt to save a non-serializable object, the JVM will fail the operation with <NotSerializableException>.

1.3.2- Data transmission.

Java permits to serialize an object over a network using RMI (Remote Method Invocation), a distributed technology of Java. RMI enables a Java client object communicates with the instance of a Java server hosted on a remote system. For example, an ATM center of your locality can interact with a bank server located in a different country.

1.3.3- Persistence.

If you want to preserve the state of a particular operation to a database, just serialize it to a byte array, and save to the database for later use.

1.3.4- Deep cloning.

In Java, it is also known as the deep copy. It causes an object to copy along with the objects to which it refers. You need to write a customized clone class to achieve this. Java serialization can save you the trouble of adding a clone class. Serializing the object into a byte array and then deserializing it to another object will fulfill the purpose.

1.3.5- Cross JVM communication.

Serialization works the same across different JVMs irrespective of the architectures they are running on.

2- How to Implement Java serialization?

Java provides out of the box solution to serialize an object. It outlines a set of generic interfaces. Your class needs to implement just one of them to enable serialization. In the next section, we’ll explore these built-in interfaces and some of the ready to use examples. Mainly, we’ll take on the following Java Serialization concepts.

2.1- Implement Java serialization using Serializable Interface.

It is the simplest way of enabling Java serialization. If you wish your class to get serialized, just implement the Java Serializable interface. It is a marker interface that doesn’t provide any method or field to implement.

Q-1 What is a marker Interface in Java?

Answer: In Java, marker Interface holds a special place because it has no methods declared in it and the class implementing it needs not to override any method. A marker interface instructs the JVM to process the object suitable for a special task. For instance, the implementation of the Serializable interface makes the JVM permit its object to write to a file.

That was a brief summary of Java Serializable Interface. Now we’ll see how to implement the Serializable interface in a Java class and apply serialization.

2.1.1- Java Serialization Example.

We’ll use a basic example for demo purpose. For the sample, you will be creating the following class files as given below.

1- <SerializationDef.java>.

2- <SerializationLib.java>.

3- <SerializationDemo.java>.

2.1.1.1- SerializationDef.java.

This file defines the Java class that we’ll use for serialization. This class represents a simple Java bean carrying some properties and getter/setter methods. By default, all the properties get serialized. But you can change this behavior. Let’s check out how?

Q-1 What is the use of transient keyword?

Answer: The <transient> is a keyword in Java. It marks a field to exclude from serialization. You can use this keyword for a variable which you don’t want to be the part of the persistent state of an object.

Q-2 Would a static member of the class get serialized?

Answer: No. A static member is associated with the class, not with the object of the class. It gets memory once during the loading of the class. And gets stored in the <PERMGEN> section of the heap.

We’ll explain the above concepts using a sample project. Please follow the parts of the sample project given below.

If you see the below class file, we’ve marked the <FeatureCount> variable as transient. So it will be excluded from being serialized.

package com.techbeamers.serialization; import java.io.Serializable; public class SerializationDef implements Serializable { private String Product; private String Feature; transient private int FeatureCount; @Override public String toString(){ return "Summary[Product("+Product+"),Feature("+Feature+"),FeatureCount("+FeatureCount+")]"; } public String getProduct() { return Product; } public void setProduct(String product) { this.Product = product; } public String getFeature() { return Feature; } public void setFeature(String feature) { this.Feature = feature; } public int getFeatureCount() { return FeatureCount; } public void setFeatureCount(int count) { this.FeatureCount = count; } } 2.1.1.2- SerializationLib.java. For serialization, you’ll need to copy the object to a file. You may then seek to deserialize it from the same file. For all this, you’ll need helper functions, you can find them in the below code snippet. You’ll notice from the code below that we are using the <ObjectOutputStream> and <ObjectInputStream> classes for serialization. Their methods take the <Object> class variable as the argument which is the parent class of all the classes in Java.

package com.techbeamers.serialization; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class SerializationLib { // Do serialize the Java object and save it to a file public static void doSerialize(Object obj, String outputFile) throws IOException { FileOutputStream fileTowrite = new FileOutputStream(outputFile); ObjectOutputStream objTowrite = new ObjectOutputStream(fileTowrite); objTowrite.writeObject(obj); fileTowrite.close(); } // Do deserialize the Java object from a given file public static Object doDeserialize(String inputFile) throws IOException, ClassNotFoundException { FileInputStream fileToread = new FileInputStream(inputFile); ObjectInputStream objToread = new ObjectInputStream(fileToread); Object obj = objToread.readObject(); objToread.close(); return obj; } } 2.1.1.3- SerializationDemo.java. Until now we’ve set the basic structure of the serialization sample. Now let’s create the main file to demonstrate the serialization process.

package com.techbeamers.serialization; import java.io.IOException; public class SerializationDemo { public static void main(String[] args) { String outputFile="serializationdemo.txt"; SerializationDef def = new SerializationDef(); def.setProduct("testProduct"); def.setFeature("testFeature"); def.setFeatureCount(10); // Serialize the object into a file. try { SerializationLib.doSerialize(def, outputFile); } catch (IOException e) { e.printStackTrace(); return; } // Deserialize from a file into an object. SerializationDef defNext = null; try { defNext = (SerializationDef) SerializationLib.doDeserialize(outputFile); } catch (ClassNotFoundException | IOException e) { e.printStackTrace(); } System.out.println("def():

--"+"

|

"+def); System.out.println(System.lineSeparator()); System.out.println("defNext():

--"+"

|

"+defNext); } } Now we are all done. And it’s time to create a Java project in Eclipse. Add all the above files into the project. Since we’ve fully verified the code, there shouldn’t be any compile error. If you still see any error, please check that JDK path is correctly set in the Eclipse preferences>>Java>>Installed JREs. Finally, when you run the project, it’ll give the following output. From the result, you can check the value of <FeatureCount> was not saved because we declared it as a transient variable. def(): -- | Summary[Product(testProduct),Feature(testFeature),FeatureCount(10)] defNext(): -- | Summary[Product(testProduct),Feature(testFeature),FeatureCount(0)] 2.2- Advance Java serialization with Inheritance. There occur two cases when we use serialization with inheritance. 1- When the parent class implements the Serializable interface, the child class does it automatically.

2- If parent class doesn’t implement the Serializable interface, then its state won’t transform into a byte stream while serializing the child class instance. For managing the 2nd case, you need to implement the following two methods in the Child class. 1- <readObject()>.

2- <writeObject()>. These methods will help in transforming the parent class state into the stream, serialize it and finally allow retrieving it. Let’s see all of this in action. 2.2.1- Java serialization example with Inheritance. We’ll demonstrate this concept through the below sample project. The first part of the project is the <ParentClass.java> file which doesn’t implement the Serializable interface. 2.2.1.1- ParentClass.java file. package com.techbeamers.serialization.inheritancedemo; public class ParentClass { private String Product; private int ProductId; public String getProduct() { return Product; } public void setProduct(String product) { this.Product = product; } public int getProductId() { return ProductId; } public void setProductId(int Id) { this.ProductId = Id; } }

2.2.1.2- ChildClass.java file.

Next is the <ChildClass.java> file which defines the read/write object method for preparing the stream of parent class state. For your information, the order of reading/writing data to the byte stream would remain the same. Another important point you’ll notice that the child class is implementing the <ObjectInputValidation> interface. It’ll allow overriding of some methods where you can add some business logic to ensure the data integrity.

package com.techbeamers.serialization.inheritancedemo; import java.io.IOException; import java.io.InvalidObjectException; import java.io.ObjectInputStream; import java.io.ObjectInputValidation; import java.io.ObjectOutputStream; import java.io.Serializable; public class ChildClass extends ParentClass implements Serializable, ObjectInputValidation { private String Brand; public String getBrand() { return Brand; } public void setBrand(String brand) { this.Brand = brand; } @Override public String toString() { return "Summary[ ProductId=" + getProductId() + ", Product=" + getProduct() + ", Brand=" + getBrand() + " ]"; } // adding helper method for serialization to save/initialize parent class // state private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { ois.defaultReadObject(); // notice the order of read and write should be same setProductId(ois.readInt()); setProduct((String) ois.readObject()); } private void writeObject(ObjectOutputStream oos) throws IOException { oos.defaultWriteObject(); oos.writeInt(getProductId()); oos.writeObject(getProduct()); } @Override public void validateObject() throws InvalidObjectException { // validate the object here if (Brand == null || "".equals(Brand)) throw new InvalidObjectException("Brand is not set or empty."); if (getProductId() <= 0) throw new InvalidObjectException("ProductId is not set or zero."); } }

2.2.1.3- InheritanceDemo.java file.

Let’s now create a demo class file to serialize/deserialize the child class data including the parent. And see whether we can retrieve the parent class state from the serialized form.

package com.techbeamers.serialization.inheritancedemo; import java.io.IOException; import com.techbeamers.serialization.SerializationLib; public class InheritanceDemo { public static void main(String[] args) { // TODO Auto-generated method stub String fileName = "childclass.txt"; ChildClass childClass = new ChildClass(); childClass.setProductId(21); childClass.setProduct("Blog"); childClass.setBrand("TechBeamers"); try { SerializationLib.doSerialize(childClass, fileName); } catch (IOException e) { e.printStackTrace(); return; } try { ChildClass newChild = (ChildClass) SerializationLib .doDeserialize(fileName); System.out.println("ChildClass output:

|

--" + newChild); } catch (ClassNotFoundException | IOException e) { e.printStackTrace(); } } }

When you execute the above code, you’ll get the following output.

ChildClass output: | --Summary[ ProductId=21, Product=Blog, Brand=TechBeamers ]

2.3- Learn to Manage lass refactoring with Java serialization.

Java serialization permits to refactor the underlying class. Following is the list of changes that are allowed in a class and won’t disturb the deserialization process.

You can add n ew members to the class.

Switching of a variable from transient to non-transient is allowed. But Serialization will consider such variables as new.

of a But Make a variable from static to non-static. Serialization will count it as a new variable.

However, Java imposes a condition for all these changes to work. You can fulfill it by adding a unique identifier, the <serialVersionUID> in the class to track the modifications under a common tag. By default, serialization will automatically compute the <serialVersionUID> by going through all the fields and methods. That’s why if you try to alter any class variable without manually specifying the version identifier, the JVM will throw the <java.io.InvalidClassExceptio> as it detects a change in the identifier value.

2.3.1- How to generate a <serialVersionUID>?

Answer:

There are three ways you can use to produce a <serialVersionUID> value.

2.3.1.1- Use the <serialver> command.

JDK bundles a tiny command line utility called the <serialver>. You just need to pass the serializable class name as command parameter to get its version identifier.

C:\Working\SerializationDemo>serialver com.techbeamers.serialization.SerializationDef SerializationDemo: static final long serialVersionUID = -2456709228636810878L;

Before you run the above command, make sure you have set the path to the JDK’s bin folder which contains the above command line tool.

2.3.1.2- Use the Eclipse IDE.

In the Eclipse IDE, hover at the serialization class. It’ll open a context menu and display three options. Choose any of the first two options as given below.

Add default serial version ID, or

Add generated serial version ID.

2.3.1.3- Assign the value of your choice.

Just pick a number you like and set as a serial version ID. But do postfix the number with an “L”.

private static final long serialVersionUID = 21L;

2.4- Learn to use the Java Externalizable Interface for Serialization.

The default serialization method is not secure and has performance issues. You can see the list below to check the performance issues with default serialization.

1- Serialization depends on the recursion mechanism. When serialization of a child class object starts, it triggers the serialization of other instance variables from the chain of parent classes which continues until it reaches the Object class of these variables. It leads to a lot of overheads.

2- While serializing an object class description information is attached to the stream. Lots of data and metadata stretch down the performance.

3- Serialization also needs a serial version ID for tracking class level changes. If you don’t set it manually, serialization calculates it automatically by going through all the fields and methods. More the size of the class more will be the time to calculate the value. So this is again a potential performance issue.

4- We can solve all of the above issues with Externalization interface.

2.4.1- What is the Externalizable interface and how is it better than the Serializable interface?

Answer: Externalization is an extension to the Serializable interface. If you want to externalize an object, then your class needs to implement the Externalizable interface and a default public constructor. In the Externalization process, only the identity of the class is added to the serialization stream. And the class is responsible for the storage and retrieval of the instance information. It gives complete control of what to add and what to leave during serialization. The basic serialization doesn’t offer the similar flexibility.

For your information, Externalizable is not a marker interface instead it exposes two methods – writeExternal and readExternal. The target class implements these methods to seize full control over the format and contents of the stream relating to the object and its supertypes. These methods must have the ability to coordinate with the object’s supertypes to save its state. They supersede the tailor-made implementation of <writeObject> and <readObject> methods.

Now it’s time to create an Eclipse sample project to demonstrate the use of the Externalizable interface. In this sample project, we’ll add the following two Java class files.

UIMap.java , this file defines a class which implements the Externalizable interface and provides the <readExternal()> and <writeExternal()> methods.

, this file defines a class which implements the Externalizable interface and provides the and methods. UIMapDemo.java, this file will create the UIMap object and test the Java serialization process via the Externalizable interface.

2.4.2- Java externalizable example.

We are embedding the source code of these files so that you can instantly add it to your local Java project. The first code snippet relates to the <UIMap.java> class file, have a look at the below code.

2.4.2.1- UIMap.java class file.

package com.techbeamers.externalization; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; public class UIMap implements Externalizable { private int id; private String locator; private String value; @Override public void writeExternal(ObjectOutput out) throws IOException { out.writeInt(id); out.writeObject(locator + "$$"); out.writeObject("##" + value); } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { id = in.readInt(); // Retrieve data in the same sequence as written locator = (String) in.readObject(); if (!locator.endsWith("$$")) throw new IOException("data integrity failed."); locator = locator.substring(0, locator.length() - 2); value = (String) in.readObject(); if (!value.startsWith("##")) throw new IOException("data integrity failed."); value = value.substring(2); } @Override public String toString() { return "UIMap[ id=" + id + ",locator=" + locator + ",value=" + value + " ]"; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getLocator() { return locator; } public void setLocator(String locator) { this.locator = locator; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } }

2.4.2.2- UIMapDemo.java class file.

Now, see the <UIMapDemo.java> file to test the functionality of the Java serialization using the Externalizable interface.

package com.techbeamers.externalization; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class UIMapDemo { public static void main(String[] args) { String fileName = "uimap.properties"; UIMap uimap = new UIMap(); uimap.setId(2); uimap.setLocator("cssSelector"); uimap.setValue("input[id=email]"); try { FileOutputStream fos = new FileOutputStream(fileName); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(uimap); oos.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } FileInputStream fis; try { fis = new FileInputStream(fileName); ObjectInputStream ois = new ObjectInputStream(fis); UIMap p = (UIMap) ois.readObject(); ois.close(); System.out.println("UIMap Object Summary:

|

-- " + p); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } } }

When we execute the above sample Java project, it’ll generate the following output.

UIMap Object Summary: | -- UIMap[ id=2,locator=cssSelector,value=input[id=email] ]

2.4.3- Download Sample Projects.

Now it’s time to download the sample project so that you can easily play around with the Java serialization examples. Please use the below link to start your download.

Download Serialization code samples.

⇓ Download Serialization Project.

We’ve lately published an interesting quiz on Java serialization concept. And we highly recommend you to attempt this questionnaire. It’ll test your knowledge as well as help in establishing your hold on the subject.

Suggested Reading: 1- Java Online Test – 20 Questions on Serialization.

Final Thought.

We wish that the A-Z Java tutorial of doing serialization in different ways would have helped you in moving a step further on the Java learning ladder. We wanted to cover the whole Java Serialization topic and the little things around it in a single article. Our goal was to make sure the post should get you almost every detail about Serialization in Java. You can get more specific detail on this topic from the Oracle’s website.

If you liked the way we’ve covered every little detail of the subject, then please use the comment box and share your feedback. Also, please forward this post to your friend circle and on the social media platforms you use.

All the Best,

TechBeamers.