Deserialization
Deserialization is the reverse process of serialization. It converts a byte stream back into a live Java object, restoring the object’s state exactly as it was at the time of serialization.
This is a high-frequency interview topic, usually asked together with serialization, transient, and serialVersionUID.
What Is Deserialization?
- Converts byte stream → Java object
- Reconstructs object state from serialized data
- Uses ObjectInputStream
- Creates a new object in memory
Why Deserialization Is Needed
- Restore objects from files
- Receive objects over network
- Reload cached objects
- Session restoration in applications
Deserialization Flow (Conceptual)
Serialized File / Network Stream
↓
ObjectInputStream.readObject()
↓
New Java Object (state restored)
Basic Deserialization Example
Serializable Class
import java.io.Serializable;
class Employee implements Serializable {
int id;
String name;
Employee(int id, String name) {
this.id = id;
this.name = name;
}
}
Deserialization Code
ObjectInputStream ois =
new ObjectInputStream(new FileInputStream("emp.ser"));
Employee e = (Employee) ois.readObject();
ois.close();
System.out.println(e.id + " " + e.name);
✔ Object recreated
✔ Same state as during serialization
✔ Constructor NOT called
Key Rules of Deserialization (Interview Critical)
- Class must implement Serializable
- serialVersionUID must match
- Constructors are NOT executed
- Static fields are NOT restored
- Transient fields get default values
- New object is created in heap
What Happens to Different Fields?
| Field Type | Deserialization Behavior |
|---|---|
| Instance variable | Restored |
| transient | Default value (null, 0, false) |
| static | Not restored |
| final | Restored (if serialized) |
serialVersionUID and Deserialization (Very Important)
private static final long serialVersionUID = 1L;
If serialVersionUID Mismatch
java.io.InvalidClassException
- ✔ Same UID → success
- ❌ Different UID → failure
Parent Class Behavior (Interview Trap)
Case 1: Parent is Serializable
- Parent fields are restored
- Parent constructor NOT called
Case 2: Parent is NOT Serializable
- Parent no-arg constructor IS called
- Parent fields initialized normally
Custom Deserialization (Advanced)
Override readObject() for custom logic.
private void readObject(ObjectInputStream ois)
throws IOException, ClassNotFoundException {
ois.defaultReadObject();
// custom validation / logic
}
✔ Used for:
- Validation
- Decryption
- Reinitializing transient fields
Deserialization Security Risks (Real-World)
- Malicious serialized data
- Arbitrary code execution
- Object injection attacks
Mitigation
- Never deserialize untrusted data
- Validate object state
- Use filtering (ObjectInputFilter)
- Prefer JSON/XML for APIs
Serialization vs Deserialization (Quick Compare)
| Aspect | Serialization | Deserialization |
|---|---|---|
| Direction | Object → Stream | Stream → Object |
| Main class | ObjectOutputStream | ObjectInputStream |
| Constructor called | ❌ No | ❌ No |
| Purpose | Save / send | Restore |
Common Beginner Mistakes
- Expecting constructor to run
- Forgetting serialVersionUID
- Assuming transient values restore
- Deserializing untrusted data
- Class mismatch between serialize/deserialize
Interview-Ready Answers
Short Answer
Deserialization converts a byte stream back into a Java object.
Detailed Answer
In Java, deserialization is the process of reconstructing an object from its serialized byte stream using ObjectInputStream. It restores the object’s state without invoking constructors and requires the class to implement Serializable with a compatible serialVersionUID.
Key Takeaway
Deserialization restores object state, not object behavior. Understand constructor behavior, transient fields, and UID compatibility to avoid runtime failures and security issues.
Deserialization Interview Cheatsheet
1. Basic Deserialization
import java.io.*;
class Demo {
public static void main(String[] args) throws Exception {
ObjectInputStream ois =
new ObjectInputStream(new FileInputStream("user.ser"));
User u = (User) ois.readObject();
System.out.println(u.id + " " + u.name);
ois.close();
}
}
2. Deserialization Order Matters
Object obj1 = ois.readObject();
Object obj2 = ois.readObject();
Explanation
Must read in same order as written.
3. transient Field After Deserialization
class User implements Serializable {
int id;
transient String password;
}
// After deserialization
password == null
4. static Field After Deserialization
class Demo implements Serializable {
static int x = 10;
}
Explanation
static value comes from class, not stream.
5. serialVersionUID Match (Successful Deserialization)
class User implements Serializable {
private static final long serialVersionUID = 1L;
}
Result
Class changes allowed (within compatibility).
6. serialVersionUID Mismatch (Failure)
// Change class structure without matching UID
Exception
InvalidClassException
7. Deserializing Inherited Object (Parent Serializable)
class Parent implements Serializable {
int x = 10;
}
class Child extends Parent {
int y = 20;
}
Child c = (Child) ois.readObject();
Result
Both x and y restored.
8. Parent NOT Serializable, Child Serializable
class Parent {
int x = 10;
}
class Child extends Parent implements Serializable {
int y = 20;
}
Result
x reset using parent no-arg constructor.
y restored from stream.
9. Custom Deserialization (readObject)
class User implements Serializable {
transient String password;
private void readObject(ObjectInputStream ois) throws Exception {
ois.defaultReadObject();
password = "recovered";
}
}
10. Deserializing ArrayList
import java.io.*;
import java.util.*;
class Demo {
public static void main(String[] args) throws Exception {
ObjectInputStream ois =
new ObjectInputStream(new FileInputStream("list.ser"));
ArrayList<String> list =
(ArrayList<String>) ois.readObject();
System.out.println(list);
ois.close();
}
}
11. Deserializing Multiple Objects
User u1 = (User) ois.readObject();
User u2 = (User) ois.readObject();
Rule
Same order as serialization.
12. Deserialization with try-with-resources
try (ObjectInputStream ois =
new ObjectInputStream(new FileInputStream("a.ser"))) {
Object obj = ois.readObject();
}
13. ClassNotFoundException Trap
try {
ois.readObject();
} catch (ClassNotFoundException e) {
System.out.println("Class missing");
}
Why
.class not found in classpath.
14. Object Graph Restoration
class Order implements Serializable {
User user;
}
Order o = (Order) ois.readObject();
Explanation
Entire object graph restored.
All referenced objects must be serializable.
15. Deserialization with Cast Safety
Object obj = ois.readObject();
if (obj instanceof User) {
User u = (User) obj;
}
16. Deserializing After JVM Restart
// Works because data stored in .ser file
Interview Point
Independent of JVM lifecycle.
17. Default Values After Deserialization
int x; // 0
String s; // null
boolean b; // false
When
Field not serialized (transient / parent field).
18. Security Trap (Untrusted Source)
// Never deserialize untrusted data
Risk
Remote code execution.
Gadget attacks.
19. Deserialization vs Constructor
// Constructor is NOT called during deserialization
Exception
Non-serializable parent constructor is called.
20. Interview Summary – Deserialization
ObjectInputStream.readObject()
Key Points
- Byte stream → object
- Constructor not invoked
- transient → default value
- UID must match
- Order matters
- All referenced objects must be serializable