Serialization and deserialization are powerful concepts that deal with converting an object into a stream of bytes and vice versa, respectively. These concepts are essential when we need to store the state of an object (e.g., to save it to a file or transmit it over a network) and later recreate it in its original form. Serialization and deserialization are useful in a variety of situations:
- Persistence: Saving the state of an object to disk for future retrieval (e.g., saving a user’s settings or game state).
- Communication: Sending objects over a network, such as when working with remote procedure calls (RPCs) or web services.
- Caching: Storing objects temporarily (e.g., in a cache) to avoid recalculating or re-fetching them.
Serialization
Serialization is the process of converting an object into a byte stream. This byte stream can be saved to a file, transferred over a network, or stored in memory. The object can then be restored (deserialized) later.
- Object: To serialize an object, we need to create an instance of
ObjectOutputStream
and pass aFileOutputStream
to it. ThewriteObject()
method is used to write the object to the output stream.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import java.io.*; public class SerializeExample { public static void main(String[] args) { Person person = new Person("John Doe", 30); try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.ser"))) { oos.writeObject(person); System.out.println("Object serialized successfully."); } catch (IOException e) { e.printStackTrace(); } } } |
The Person
object is serialized and stored in a file named person.ser
.
- Collection: We can serialize a collection just like any other object. Here’s an example of serializing an
ArrayList
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import java.io.*; import java.util.ArrayList; public class SerializeCollectionExample { public static void main(String[] args) { ArrayList<String> names = new ArrayList<>(); names.add("Alice"); names.add("Bob"); try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("names.ser"))) { oos.writeObject(names); System.out.println("Collection serialized successfully."); } catch (IOException e) { e.printStackTrace(); } } } |
This serializes an ArrayList
of String
objects into the file names.ser
.
Deserialization
Deserialization is the reverse process of serialization: it involves converting a byte stream back into an object. During deserialization, the byte stream is read, and an exact replica of the original object is created, with its state restored.
- Object: To deserialize an object, we use the
ObjectInputStream
class, which reads the byte stream from a file and converts it back into an object using thereadObject()
method.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import java.io.*; public class DeserializeExample { public static void main(String[] args) { try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.ser"))) { Person person = (Person) ois.readObject(); System.out.println("Object deserialized successfully."); System.out.println("Name: " + person.getName() + ", Age: " + person.getAge()); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } } } |
The Person
object is read from the file and cast back into its original class.
- Collection: To deserialize a collection, we simply cast the read object into the appropriate collection type.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import java.io.*; import java.util.ArrayList; public class DeserializeCollectionExample { public static void main(String[] args) { try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("names.ser"))) { ArrayList<String> names = (ArrayList<String>) ois.readObject(); System.out.println("Collection deserialized successfully."); System.out.println("Names: " + names); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } } } |
This code deserializes the ArrayList
from the file names.ser
and prints its contents.
Custom Serialization
While Java provides default serialization, we might need more control over the process. Custom serialization allows us to specify how an object should be serialized and deserialized by overriding two special methods: writeObject()
and readObject()
.
Let’s say we have a class where we want to serialize only certain fields or add custom logic during the serialization process. We can override writeObject()
and readObject()
as shown below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
import java.io.*; public class CustomSerializationExample implements Serializable { private String name; private int age; private transient String password; // transient field will not be serialized // Constructor, getters, setters private void writeObject(ObjectOutputStream oos) throws IOException { oos.defaultWriteObject(); // Write default fields oos.writeObject(password); // Serialize password manually } private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { ois.defaultReadObject(); // Read default fields password = (String) ois.readObject(); // Deserialize password manually } } |
The password
field is marked as transient
, meaning it won’t be serialized by default. However, it is explicitly serialized and deserialized using custom methods.