devxlogo

Implement Persistent Objects with Java Serialization

Implement Persistent Objects with Java Serialization

Whether it is a word-processing application that saves documents to a disk, a utility that remembers its configuration for subsequent use, or a game that allows players to assume world domination and then set it aside for the night, the ability to store and later retrieve data is vital. Without it, software would be hardly more effective than the typewriter?users would have to retype their data to make further modifications once their applications exit.

Most Java programmers are comfortable writing and reading basic Java data types like strings and integers to and from disk. However, writing code that saves abstract data types, like any object you have written yourself, can become both complex and repetitive. First, you have to create a specification for the proposed file structure. Next, you have to implement save and restore functions that convert the object data to and from primitive data types, and finally you need to test it with sample data.

If you need to store new data to the application later, you’ll have to modify the file specification, as well as the save and restore methods. It would be nice if you could simply save an abstract data type?like a linked list, for example?just as easily as you save, say, an integer data value, without having to iterate through all its nodes, saving each one in turn.

Happily, Java does provide a solution that does just that, object serialization. Object serialization takes an object’s state and converts it to a stream of data. With object serialization, making any object persistent becomes easy?you dont have to write custom code to save object member variables. The object can be restored at a later time, even at another location. In fact, you can even move an object from one computer to another and have it maintain its state. Not only is this a very cool feature of Java, but it also is easy to use.Serializing Objects
Java makes serializing objects easy. You can make any object whose class implements the java.io.Serializable interface persistent with only a few lines of code. Unlike implementing the ActionListener event-handling interface, for example, no extra methods need to be added to implement the interface?the purpose of the interface is simply to identify which classes can be safely serialized and which cannot at runtime. You need only add the implements keyword to your class declaration to identify your classes as serializable, like so:

public class UserData implements java.io.Serializable

Once a class is serializable, you can write the object to any OutputStream, such as to disk. To achieve this, you must first create an instance of java.io.ObjectOutputStream and pass the constructor an existing OutputStream instance. You could use code like this:

// Use a FileOutputStream to send data to a file// called myobject.data.FileOutputStream f_out = new     FileOutputStream ("myobject.data");// Use an ObjectOutputStream to send object data to the// FileOutputStream for writing to disk.ObjectOutputStream obj_out = new     ObjectOutputStream (f_out);// Pass our object to the ObjectOutputStream's// writeObject() method to cause it to be written out// to disk.obj_out.writeObject (myObject);

And that’s it. In just three lines of code, you have written “myObject” (which you can consider just any arbitrary object) out to a disk file. Note that any Java object that implements the serializable interface, including those that are part of the Java standard class library, can be written to an output stream this way.

Furthermore, any objects that are referenced by a serialized object will also be stored, provided they also are serializable. This means that arrays, vectors, lists, and collections of objects can be saved in the same fashion?without having to manually save each item individually. This can lead to significant time and code savings.

Think about it: if you have an object that contains other objects, you still can save the whole kit and caboodle to disk with no more code than the few lines above. It really can’t get much easier than that!Restoring Objects from a Serialized State
Once you have saved your data type to a file, you have to be able to read it back in again. Reading objects back is almost as easy as writing them. The one catch is that at runtime the Java runtime engine can never be completely sure what type of data to expect. After all, a data stream containing serialized objects may well contain a mixture of different object classes.

So Java simply will read data back as generic java.lang.Object types. You need to explicitly cast this generic object to a particular class, a relatively straightforward procedure. You simply tell Java to interpret a specific set of data as an instance of a specific data type or class. You can do this by first checking the object’s class, using the instance of operator, and then casting to the correct class, like so:

// Read from disk using FileInputStream.FileInputStream f_in = new    FileInputStream ("myobject.data");// Read object using ObjectInputStream.ObjectInputStream obj_in = new ObjectInputStream (f_in);// Read an object.Object obj = obj_in.readObject ();// Is the object that you read in, say, an instance// of the Vector class?if (obj instanceof Vector){  // Cast object to a Vector  Vector vec = (Vector) obj;  // Do something with vector ...}else // ... the object is some other type ...

Further Issues with Serialization
As you can see, it’s relatively easy to serialize an object. Whenever new fields are added to an object, they will be saved automatically without requiring modification to your save and restore code.

However, this behavior is not desirable in all cases. For example, transmitting a password member variable to third parties over a network connection might not be safe. You might need to leave it blank. In this case, you can use a special keyword (“transient”). The transient field indicates that a particular member variable should not be saved. Though not used often, it’s an important keyword to remember. Use it like so:

public class UserSession implements java.io.Serializable{  String username;  transient String password;}

Putting It All Together in a Sample Program
Let’s construct a linked list abstract data type to manage a dynamic list of integer values. A list is a common and useful data structure. Unlike an array, a list doesn’t have a predefined number of contents. You can add elements to it so long as the computer has enough memory to store them all! Additionally, you can add new items to, or remove them from, any point in the list without having to shuffle all the other elements around.

The lists in our sample datatype are made up of individual “nodes” of integers. Listing 1 contains the code for an individual “IntNode” object. Listing 2 strings this together to create an “IntList” object with methods to add or remove nodes and to list all its contents.

You will see that both classes implement the Serializable interface. Note that both classes need to be serializable, because the list is made up of nodes?to save the list, Java needs to be able to save each node. Listing 3 contains a test program to run your list class through some exercises, including, of course, serialization! (See Figure 1 for the output from a sample run of the test program.)

First, build up a list (list1) with four data items. Then serialize your list to a disk file. Next, delete the first item from list1 and display its contents to the screen so you can verify that the list really has changed. Now, create a new list instance (list2) that has no items. Display its contents to prove this. Using serialization, load the saved data into list2 to populate it. Finally, display the contents of list2. You will see it has four data items, in the same order they appeared when you saved them from list1.

Figure 1: Sample Run of the Test Program

Persistent Object Implementation Made Easy
Java’s support for object serialization makes implementing persistent objects extremely easy. By contrast, saving, and restoring every field of an object is complex and repetitive. You certainly could write your own serialization mechanism, but the simplicity Java provides in its serialization is hard to beat. Java serialization offers developers the following:

  • It reduces the amount of time needed to save and restore object or application state.
  • It eliminates the complexity involved with save and restore operations.
  • It avoids the need to create a new file format.
  • It makes travel over a network connection easier for objects.

With relatively little effort, you can apply serialization to a variety of tasks. Not only do applications benefit from serialization, but applets do also. Rather than specifying a long list of parameters or performing time-consuming initialization and parsing, an applet can simply reload a configuration object whose member variables contain all the information the applet needs to execute.

With a little imagination, serialization may just have a place in your next project!

devxblackblue

About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist