[Chapter 8] 8.3 Serialization

#

| Chapter 8 Input/Output Facilities |

## 8.3 Serialization

Using streams and files, you can write an application that saves and loads its data to a disk drive. Java 1.1 provides an even more powerful mechanism called object serialization that does a lot of the work for you. In its simplest form, object serialization is an automatic way to save and load an object. However, object serialization has depths that we cannot plumb within the scope of this book, including complete control over the serialization process and interesting conundrums like class versioning.

Basically, any class that implements the `Serializable` interface can be saved and restored from a stream. Special stream subclasses, `ObjectInputStream` and `ObjectOutputStream`, are used to serialize primitive types and objects. Subclasses of `Serializable` classes are also serializable. The default serialization mechanism saves the value of an object's non`static` and non`volatile` member variables.

One of the tricky things about serialization is that when an object is serialized, any object references it contains should also be serialized. We'll see this in an upcoming example. The implication is that any object we serialize must only contain references to `Serializable` objects. There are ways around this problem, like marking nonserializable members as `volatile` or overriding the default serialization mechanisms.

In the following example, we create a `Hashtable` and write it to a disk file called `h.ser`.

    import java.io.*;
    import java.util.*;
    public class Save {
      public static void main(String[] args) {
        Hashtable h = new Hashtable();
        h.put("string", "Gabriel Garcia Marquez");
        h.put("int", new Integer(26));
        h.put("double", new Double(Math.PI));

        try {
          FileOutputStream fileOut = new FileOutputStream("h.ser");
          ObjectOutputStream out = new ObjectOutputStream(fileOut);
          out.writeObject(h);
        }
        catch (Exception e) {
          System.out.println(e);
        }
      }
    }

First we construct a `Hashtable` with a few elements in it. Then, in the three lines of code inside the `try` block, we write the `Hashtable` to a file called `h.ser`, using the `writeObject()` method of `ObjectOutputStream`. The `ObjectOutputStream` class is a lot like the `DataOutputStream` class, except that it includes the powerful `writeObject()` method. The `Hashtable` object is serializable because it implements the `Serializable` interface.

The `Hashtable` we created has internal references to the items it contains. Thus, these components are automatically serialized along with the `Hashtable`. We'll see this in the next example when we deserialize the `Hashtable`.

    import java.io.*;
    import java.util.*;
    public class Load {
      public static void main(String[] args) {
        try {
          FileInputStream fileIn = new FileInputStream("h.ser");
          ObjectInputStream in = new ObjectInputStream(fileIn);
          Hashtable h = (Hashtable)in.readObject();
          System.out.println(h.toString());
        }
        catch (Exception e) {
          System.out.println(e);
        }
      }
    }

In this example, we read the `Hashtable` from the `h.ser` file, using the `readObject()` method of `ObjectInputStream`. The `ObjectInputStream` class is a lot like `DataInputStream`, except it includes the `readObject()` method. The return type of `readObject()` is `Object`, so we need to cast it to a `Hashtable`. Finally, we print out the contents of the `Hashtable` using its `toString()` method.

Files |  | Data compression