Apr 13, 2012

Object Serialization

This section introduces object serialization and covers the following topics:
Ø     What is object serialization and how does it work?
Ø     Features of a serializable class
Ø     Externalizable

What is object serialization?
           Object serialization lets you take all the data attributes, write them out as an object, and read them back in as an object. Object serialization is quite useful when you need to use object persistence. GUI builders of JavaBeans use serialization to store the attributes of a JavaBean so that it can be accessed or modified by others.
You could actually use DataOuputStreams and DataInputStreams to write each attribute out individually, and then you could read them back in on the other end. But you want to deal with the entire object, not its individual attributes. You want to be able to simply store away an object or send it over a stream of objects. Object serialization takes the data members of an object and stores them away or retrieves them, or sends them over a stream.
You have the ObjectInput interface, which extends the DataInput interface, and ObjectOutput interface, which extends DataOutput , so you are still going to have the methods readInt() and writeInt() and so forth. ObjectInputStream , which implements ObjectInput , is going to read what ObjectOutputStream produces.

How object serialization works
         If you want to use the ObjectInput and ObjectOutput interface, the class must be serializable. How is a class serializable?
The serializable characteristic is assigned when a class is first defined. Your class must implement the Serializable interface. This marker interface says to the Java virtual machine that you want to allow this class to be serializable. You don't have to add any additional methods or anything.
There are a couple of other features of a serializable class. First, it has to have a zero parameter constructor. When you read the object, it needs to be able to construct and allocate memory for an object, and it is going to fill in that memory from what it has read from the serial stream. The static fields, or class attributes, are not saved because they are not part of an object. If you do not want a data attribute to be serialized, you can make it transient. That would save on the amount of storage or transmission required to transmit an object.

Using ObjectOutputStream: Example code
           Let's see how this works. A FileObjectStream is created using object.dat , which is going to be used to store away objects.
You create ObjectOutputStream using that file. Any other OutputStream  such as that returned by getOutputStream() for a socket, could have been used. And now you have YourClass. This is whatever class you have made up. You create an object of that class. If you want to store that away on the ObjectOutputStream , you simply call writeObject() and pass it the object. That's it!
The class could have 20 attributes in it or 50 attributes; it doesn't matter. All of those attributes are automatically stored away. The class information is stored automatically.
The Java code knows what's in a class and knows the attributes in a class. In fact, the first time the code stores such an object, it stores a couple of markers about what the class is.Calling writeObject() is all that is necessary to store an object.
Here is the example code:
FileOutputSream fos = new FileOutputStream("object.dat");
ObjectOutputStream oos = new ObjectOutputStream(fos);
YourClass yc = new YourClass();
oos.writeObject(yc);

Reading an object from a file: Example code
           Now let's read that object from the file. Create a FileInputStream using the file object.dat that was written in the previous panel. That file is used as the source for an ObjectInputStream. You want to read the object, so we call readObject() and the object is read off the file. The attributes of the YourClass object are filled in with the data we have stored away.
The readObject() method returns a reference to an Object class object. You wrote out a YourClass object, so you have to cast the reference to YourClass. You have to keep track of the order in which you wrote things out. If you stored away a YourClass object, and then you stored away an AnotherClass object, you have to read them back in the same sequence.
Typically, you would write things out in a sequence, and then you would read them back in the same sequence. However, there are some alternative approaches, discussed in the next panel.
Here is the example code:
FileInputStream fis = new FileInputStream ("object.dat");
ObjectInputStream ois = new ObjectInputStream (fis);
YourClass yc;
yc = (YourClass) ois.readObject();


Alternative ways to read back: Example code
           If you do not know the order in which the objects were stored, you can test for the class of the object that was returned by readObject() using instanceof , or you can use the getClass() method to determine the class of the object. Then you can assign the returned value to the appropriate object using a cast. You can do more elaborate reading and writing as you read back an object, test what it is, and then do an appropriate cast.
That's all you have to do to store away an object in a file. Now, you want to transmit it over a socket. All the values in that object are transmitted over a socket if you used the appropriate input and output streams from the socket object. Remote method invocation (RMI) passes objects using object serialization over a socket.
Here is the example code:
FileInputStream fis = FileInputStream("object.dat");
ObjectInputStream ois = new ObjectInputStream(fis);
Object object;
object = ois.readObject();
   if (object instanceof YourClass)
   {
      YourClass yc = object;
      // Perform operations with yc;
   }
   else if (object instance of AnotherClass)
   {
      AnotherClass ac = object;
      // Perform operations with ac
   }

Add serializable: Example code
         We said before that if the base class implements Serializable , all you have to do is mark your derived class Serializable . But what if your base class doesn't implement it? You can still implement Serializable in your derived class.
If the base class does not implement Serializable but you want to use serialization, you simply have to get all the attributes out of the base class and store them away. Your additional attributes are stored automatically, but the base class attributes are not. You have to use get() methods, and if the base class does not have gets and sets for its attributes, then you won't be able to serialize the base class. You need to define your own readObject() and writeObject() methods, which we describe next.
Here is the example code:
class ABaseClass
{
   private int value;
   int getValue()
   {
      return value;
   }
   void setValue(int value)
   {
      this.value = value;
   }
}
class YourClass extends ABaseClass implements Serializable
{
//..
}

Custom serialization: Example code
          You may want to use custom serialization if the base class does not support serialization and  for some reason you don't like the default customization. Define your own readObject() and writeObject() methods. The fields or attributes are no longer automatically serialized if you define these methods. You have to take care of saving and restoring each of your attributes.
To store away the non-transient and non-static attributes for each object, call defaultWriteObject(). The attributes can be loaded with defaultReadObject().You can store and load additional values in your method, for instance, ones that you have declared to be transient. If the class you derived from is serializable, then your data for the super class is already taken care of. All you have to do then is add your own custom code.
The example code below shows how readObject() and writeObject() are coded. Note that ABaseClass does not implement Serializable, but it does have getValue() and setValue().
Here is the example code:
class ABaseClass
{
   private int value;
   int getValue()
   {
     return value;
   }
   void setValue(int value)
   {
     this.value = value;
   }
}
class YourClass extends ABaseClass implements Serializable
{
   int another;
   private void readObject(ObjectInputStream ois)
throws IOException, ClassNotFoundException
   {
      ois.defaultReadObject();
      setValue(ois.readInt());
   }
   private void writeObject(ObjectOutputStream oos)
throws IOException
   {
      oos.defaultWriteObject();
      oos.writeInt(getValue());
   }
}

Externalizable: Example code
             As you become more experienced with Java programming, you may decide you would like to customize the way things are done. You want to implement your own complete way of doing data persistence.
If you want to add your own custom code for storing away base class or superclass data, you must implement Externalizable. Externalizable has two methods: readExternal() and writeExternal().In this case, you are fully responsible for everything.
Here is the example code:
private void readExternal(ObjectInputStream ois)
throws IOException, ClassNotFoundException
private void writeExternal(OutputStream os)throws IOException


0 comments :

Post a Comment