Hello! Welcome to the final lesson in our module on Advanced Java. We've journeyed through complex concurrency topics, culminating in our last discussion on asynchronous programming with CompletableFuture. Now, we shift our focus from concurrency to another fundamental aspect of Java I/O that is a classic interview favorite.
Today's learning outcome is to explain the Java serialization mechanism, including the roles of the Serializable interface and the 'transient' keyword. Serialization is the process of converting an object's state into a byte stream, which can then be stored on disk, sent across a network, or saved in a database. Understanding this mechanism is crucial for many distributed systems and is a staple of core Java interview questions.
1. What is Serialization and Why Do We Need It?
At its core, serialization is about capturing the current state of a Java object and turning it into a sequence of bytes. The reverse process, deserialization, reconstructs the object from that byte stream.
This capability is fundamental for two main reasons:
- Persistence: Saving the state of an object to a file on disk, so it can be restored later, even after the JVM has shut down.
- Communication: Sending an object from one Java application to another, for instance, over a network in a client-server or microservices architecture.
The key feature of Java's serialization is that the byte stream is platform-independent. An object serialized on a Windows machine can be deserialized on a Linux machine without any issues.

To get a quick overview of this process, watch the first part of the following video.
Serialization Deserialization & Externalization | Java Interview Questions and Answer | Code Decode
This video from Code Decode provides a clear, practical introduction to what serialization is and why it's used.
Watch from the beginning (00:22) to 01:50. Focus on the core definition of serialization as the conversion of Java objects into byte streams for transfer or storage.
2. The Core Mechanism: Serializable and I/O Streams
To make a Java class serializable, you must implement the java.io.Serializable interface. This is a marker interface, meaning it has no methods to implement. Its sole purpose is to "mark" the class and signal to the JVM that its instances are allowed to be serialized.
The actual serialization and deserialization work is done using two key stream classes:
java.io.ObjectOutputStream: Wraps anOutputStream(likeFileOutputStream) and provides thewriteObject()method to serialize an object.java.io.ObjectInputStream: Wraps anInputStream(likeFileInputStream) and provides thereadObject()method to deserialize an object.
The following video segments demonstrate this process with code, showing how to make a class serializable and then write it to and read it from a file.
Serialization Deserialization & Externalization | Java Interview Questions and Answer | Code Decode
Let's continue with the Code Decode video. These next sections provide a step-by-step code demonstration of the entire serialization and deserialization lifecycle.
Watch from 01:50 to 12:48. Pay close attention to: How the Serializable interface is implemented. The use of ObjectOutputStream and FileOutputStream for writing the object. The use of ObjectInputStream and FileInputStream for reading the object back. The necessity of casting the result of readObject() back to the original class type.
Here's a summary of the code structure:
// 1. The class must implement Serializable
public class Employee implements java.io.Serializable {
private int id;
private String name;
// constructors, getters, setters...
}
// 2. To Serialize (write) the object
Employee emp = new Employee(1, "John Doe");
try (FileOutputStream fileOut = new FileOutputStream("employee.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut)) {
out.writeObject(emp);
}
// 3. To Deserialize (read) the object
Employee empFromFile;
try (FileInputStream fileIn = new FileInputStream("employee.ser");
ObjectInputStream in = new ObjectInputStream(fileIn)) {
empFromFile = (Employee) in.readObject();
}
3. Controlling Serialization: transient and static
By default, Java's serialization mechanism tries to save the values of all of an object's instance fields. However, you often need more control. This is where the transient and static keywords become important.
The transient Keyword
You use the transient keyword to mark a field that should not be serialized. When an object is deserialized, a transient field will be initialized to its default value (e.g., 0 for int, false for boolean, null for object references).
Why would you do this?
- Sensitive Data: To prevent sensitive information, like passwords or credit card numbers, from being written to a byte stream.
- Derived Data: If a field's value can be calculated from other fields, there's no need to serialize it. You can simply recalculate it after deserialization.
- Non-Serializable Fields: If a field holds an object that doesn't implement
Serializable(like a thread pool or a database connection), you must mark it astransientto avoid aNotSerializableException.
The static Keyword
static fields are also not part of the serialization process. This is a crucial interview point. Serialization saves the state of an object instance. static fields belong to the class, not to any individual instance. Therefore, they are not included in the object's serialized state.
Serialization - Top 25 interview questions
The following resource provides a concise, question-and-answer style explanation of these keywords, which is excellent for interview preparation.
Read Question 6 ('How can you avoid certain member variables from getting Serialized?') and Question 11 ('Why static member variables are not part of java serialization process?'). This will solidify your understanding of both transient and static.
Test your understanding!
You have a User class with fields username, password, and a logger. The logger is a java.util.logging.Logger instance, which is not serializable. How would you modify the class to make it correctly serializable while ensuring the password is not saved?
import java.io.Serializable;
import java.util.logging.Logger;
public class User implements Serializable {
private String username;
private String password; // Sensitive
private Logger logger = Logger.getLogger(User.class.getName()); // Not Serializable
}
Show answer
You should mark both the password and logger fields as transient.
import java.io.Serializable;
import java.util.logging.Logger;
public class User implements Serializable {
private String username;
private transient String password; // Mark as transient to prevent serialization
private transient Logger logger = Logger.getLogger(User.class.getName()); // Must be transient as Logger is not Serializable
}
After deserialization, password will be null and logger will also be null. You would typically re-initialize the logger in a custom readObject method or a constructor if needed.
4. Versioning with serialVersionUID
This is one of the most important and frequently asked interview topics related to serialization.
What happens if you serialize an object, then change the class (e.g., add a new field), and then try to deserialize the old object? By default, this will fail with an java.io.InvalidClassException.
To prevent this, the serialization mechanism uses a version number called serialVersionUID.
- If you don't declare it: The JVM generates one at runtime based on the class's structure (name, fields, methods, etc.). Any change to the class structure will result in a different
serialVersionUID. - If you declare it: You explicitly provide a
private static final long serialVersionUID. Now, if you make a compatible change (like adding a new field), theserialVersionUIDremains the same, and deserialization will still work. The newly added field will simply be initialized to its default value.
Best practice is to always declare serialVersionUID in your serializable classes. This gives you control over which class changes are compatible and which are not.
The following video segment explains this concept very well.
Serialization Deserialization & Externalization | Java Interview Questions and Answer | Code Decode
The Code Decode video has an excellent section explaining the importance of serialVersionUID and the consequences of not declaring it.
Watch from 12:48 to 17:45. Focus on why serialVersionUID is needed for versioning, what happens if you don't declare it, and how it helps avoid InvalidClassException.
5. Advanced Topics and Interview Pitfalls
For a senior role, you'll be expected to know more than just the basics. Here are some common follow-up questions.
Composition and NotSerializableException
If your class contains a field that is a reference to another object, that object's class must also implement Serializable. If it doesn't, the JVM will throw a java.io.NotSerializableException at runtime when you try to serialize the parent object. The only way around this is to mark the field as transient.
Serialization - Top 25 interview questions
This is a classic 'gotcha' question. The 'Java Made So Easy' article clearly explains this scenario.
Read Question 13, 'What will happen if one the member of class does not implement Serializable interface?'.
Inheritance
- If a superclass is
Serializable, its subclasses are also serializable by default. - If a subclass is
Serializablebut its superclass is not, the fields of the superclass are not serialized. During deserialization, the JVM will call the no-argument constructor of the non-serializable superclass to initialize its fields. This means any non-serializable superclass must have a no-arg constructor.
Customizing Serialization
While Serializable provides an automatic mechanism, you can gain full control.
writeObject()andreadObject(): By providingprivatemethods with these exact signatures in yourSerializableclass, you can define your own custom serialization logic. The JVM will invoke these instead of the default mechanism. This is useful for encrypting fields or handlingtransientfields that need special initialization.Externalizableinterface: This interface extendsSerializableand requires you to implementwriteExternal()andreadExternal(). It gives you complete, mandatory control over the serialization process, disabling the default mechanism entirely.
Conclusion
You've now covered the Java serialization mechanism, a core concept that bridges object-oriented programming with I/O and network communication. It's a fundamental topic that demonstrates a deep understanding of the Java platform.
Key Takeaways:
- Purpose: Serialization converts an object's state into a byte stream for persistence or transmission.
- Core Interface: A class must implement the
java.io.Serializablemarker interface to be eligible for serialization. - Core Classes:
ObjectOutputStream.writeObject()serializes, andObjectInputStream.readObject()deserializes. - Controlling Fields: The
transientkeyword excludes a field from serialization, andstaticfields are never serialized as they belong to the class, not the instance. - Versioning: Always declare a
private static final long serialVersionUIDto manage class evolution and preventInvalidClassException. - Common Pitfalls: Be aware of
NotSerializableExceptionwith composed objects and the special handling of inheritance when a superclass is not serializable.
Preview of the Next Lesson:
This lesson marks the end of our module on advanced core Java topics. We will now transition into the world of frameworks, which build upon these core principles. Our next module, "Spring & Spring Boot Core," begins with the very foundation of the Spring framework. In the next lesson, we will explain Inversion of Control (IoC), Dependency Injection (DI), and compare constructor vs. setter injection.