Serialization is the process of converting a Java object into a byte stream — so it can be:
- Saved to a file
- Sent over a network
- Stored in a database
- Transferred between JVMs
Later, you can deserialize that byte stream back into the original object, preserving its state.
🧩 Why Use Serialization?
Use Case | Why Serialization Helps |
---|---|
Save game/app state | Save object state to file and load later |
Network communication | Send object from client to server |
Cache in memory/disk | Persist complex data structures easily |
Deep copy | Create a clone by serializing/deserializing |
📦 In Java: The Serializable
Interface
To make an object serializable, it must:
public class MyData implements Serializable {
private int id;
private String name;
}
✅ Marker interface → has no methods, just signals to Java: “this object can be serialized”
🔧 Basic Serialization Example
1. Write Object to File (Serialization)
import java.io.*;
MyData data = new MyData(1, "Stanley");
try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("data.ser"))) {
out.writeObject(data);
}
2. Read Object from File (Deserialization)
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.ser"))) {
MyData readData = (MyData) in.readObject();
System.out.println(readData.name); // Stanley
}
🛑 Important Notes
Topic | Explanation |
---|---|
serialVersionUID | A version ID to ensure compatibility across versions of a class |
transient | Keyword to skip fields during serialization |
Not all types are serializable | E.g., open FileInputStream or Thread can’t be saved |
Java default format is binary | Not human-readable (can use JSON/XML libraries if needed) |
🧵 TL;DR
Concept | Description |
---|---|
Serialization | Convert object → byte stream |
Deserialization | Byte stream → object |
Interface | Serializable |
Use Cases | Saving state, network transport, deep cloning |
Tools | ObjectOutputStream , ObjectInputStream |
🧵 TL;DR
Concept | Description |
---|---|
Serialization | Convert object → byte stream |
Deserialization | Byte stream → object |
Interface | Serializable |
Use Cases | Saving state, network transport, deep cloning |
Tools | ObjectOutputStream , ObjectInputStream |
When we say Java serialization uses a byte stream, we’re really talking about the default built-in serialization mechanism (ObjectOutputStream
/ ObjectInputStream
). But that’s not the only option — it just happens to be the lowest-level, most portable format across JVMs.
Let’s answer your question directly:
🧠 Why Java serialization uses byte streams by default
✅ 1. Platform-independent
- Byte streams make it easy to store and restore objects on any machine running Java.
- No worry about line endings, encodings, locales — it’s all binary-safe.
✅ 2. Saves complete internal structure
- Includes type info, references, field values (even for deeply nested objects).
- The binary format is compact and efficient, unlike verbose formats like JSON or XML.
✅ 3. Supports references & object graphs
- Java serialization preserves object identity, cycles, and shared references:
Person p = new Person("Stanley");
List<Person> list = Arrays.asList(p, p); // same object twice
→ After serialization/deserialization, the two entries in the list still point to the same object — that’s very hard to do with plain text formats!
🔧 Step-by-Step: How Java Serialization Preserves Object Identity (Without Using Pointers)
🔹 Step 1: You create an object
Person p = new Person("Stanley");
This object lives in memory (heap), and has some ID in memory (e.g., 0x12345
— invisible to you).
🔹 Step 2: You put that object into a list twice
List<Person> list = Arrays.asList(p, p);
So this list contains two references to the same exact object.
list.get(0) → p
list.get(1) → p
So:
list.get(0) == list.get(1) // true ✅
🔹 Step 3: You serialize the list
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("data.ser"));
out.writeObject(list);
What happens under the hood?
- Java writes an internal object reference table.
- It finds the list → assigns it Object #1.
- It starts writing the first
Person p
→ assigns it Object #2. - When it gets to the second
p
, Java recognizes it’s already serialized, so instead of serializing it again, it writes something like:
“Hey, this is the same as Object #2 — don’t serialize it again, just reference it.”
✅ It keeps track internally, using object identity (==
), not memory addresses.
🔹 Step 4: You deserialize the list
ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.ser"));
List<Person> deserializedList = (List<Person>) in.readObject();
What Java does:
- It sees Object #1 is a
List
. - Then it sees Object #2 is a
Person("Stanley")
. - Then when it reaches the second element in the list and sees it refers to Object #2 again, it reuses the same
Person
object already created.
So:
deserializedList.get(0) == deserializedList.get(1) // true ✅
Even though it’s not the same memory as before, Java reconstructed the object structure identically.
✅ During serialization, Java writes each object once, and just refers to it afterward if it appears again.
✅ During deserialization, Java reuses the same instance each time that reference shows up again.
So:
- It preserves identity (same object reused),
- But it’s not the same memory as before (new heap),
- Yet
==
still returnstrue
because both references point to the same recreated instance.