20.8. Chapter Summary

 
[Page 617]

18.6. Object I/O

DataInputStream / DataOutputStream enables you to perform I/O for primitive type values and strings. ObjectInputStream / ObjectOutputStream enables you to perform I/O for objects in addition to primitive type values and strings. Since ObjectInput - Stream / ObjectOutputStream contains all the functions of DataInputStream / DataOutputStream , you can replace DataInputStream / DataOutputStream completely with ObjectInputStream / ObjectOutputStream .

ObjectInputStream extends InputStream and implements ObjectInput and ObjectStreamConstants , as shown in Figure 18.14. ObjectInput is a subinterface of DataInput . DataInput is shown in Figure 18.9. ObjectStreamConstants contains the constants to support ObjectInputStream / ObjectOutputStream .

Figure 18.14. ObjectInputStream can read objects, primitive type values, and strings.

ObjectOutputStream extends OutputStream and implements ObjectOutput and ObjectStreamConstants , as shown in Figure 18.15. ObjectOutput is a subinterface of DataOutput . DataOutput is shown in Figure 18.10.

Figure 18.15. ObjectOutputStream can write objects, primitive type values, and strings.

You may wrap an ObjectInputStream / ObjectOutputStream on any InputStream / OutputStream using the following constructors:

  // Create an ObjectInputStream    public   ObjectInputStream(InputStream in)  // Create an ObjectOutputStream    public   ObjectOutputStream(OutputStream out) 

Listing 18.4 writes student names , scores, and current date to a file named object.dat .

Listing 18.4. TestObjectOutputStream.java
(This item is displayed on pages 617 - 618 in the print version)
 1   import   java.io.*; 2 3   public class   TestObjectOutputStream { 

[Page 618]
 4   public static void   main(String[] args)   throws   IOException { 5  // Create an output stream for file object.dat  6  ObjectOutputStream output =  7    new   ObjectOutputStream(   new   FileOutputStream(   "object.dat"   ));  8 9  // Write a string, double value, and object to the file  10 output.writeUTF(   "John"   ); 11 output.writeDouble(   85.5   ); 12  output.writeObject(   new   java.util.Date());  13 14  // Close output stream  15 output.close(); 16 } 17 } 

An ObjectOutputStream is created to write data into file object.dat in lines 6 “7. A string, a double value, and an object are written to the file in lines 10 “12. To improve performance, you may add a buffer in the stream using the following statement to replace lines 6 “7:

 ObjectOutputStream output =   new   ObjectOutputStream(   new   BufferedOutputStream(   new   FileOutputStream(   "object.dat"   ))); 

Multiple objects or primitives can be written to the stream. The objects must be read back from the corresponding ObjectInputStream with the same types and in the same order as they were written. Java's safe casting should be used to get the desired type. Listing 18.5 reads data back from object.dat .

Listing 18.5. TestObjectInputStream.java
 1   import   java.io.*; 2 3   public class   TestObjectInputStream { 4   public static void   main(String[] args) 5   throws   ClassNotFoundException, IOException { 6  // Create an input stream for file object.dat  7  ObjectInputStream input =  8    new   ObjectInputStream(   new   FileInputStream(   "object.dat"   ));  9 10  // Write a string, double value, and object to the file  11 String name = input.readUTF(); 12   double   score = input.readDouble(); 13 java.util.Date date = (java.util.Date)(  input.readObject()  ); 14 System.out.println(name +   " "   + score +   " "   + date); 15 16  // Close output stream  17 input.close(); 18 } 19 } 

The readObject() method may throw java.lang.ClassNotFoundException . The reason is that when the JVM restores an object, it first loads the class for the object if the class has not been loaded. Since ClassNotFoundException is a checked exception, the main method declares to throw it in line 5. An ObjectInputStream is created to read input from object.dat in lines 7 “8. You have to read the data from the file in the same order and format as they were written to the file. A string, a double value, and an object are read in lines 11 “13. Since readObject() returns an Object , it is cast into Date and assigned to a Date variable in line 13.


[Page 619]

18.6.1. The Serializable Interface

Not every object can be written to an output stream. Objects that can be written to an object stream are said to be serializable . A serializable object is an instance of the java.io.Serializable interface, so the class of a serializable object must implement Serializable .

The Serializable interface is a marker interface. Since it has no methods , you don't need to add additional code in your class that implements Serializable . Implementing this interface enables the Java serialization mechanism to automate the process of storing objects and arrays.

To appreciate this automation feature and understand how an object is stored, consider what you need to do in order to store an object without using this feature. Suppose you want to store a JButton object. To do this you need to store all the current values of the properties (e.g., color , font, text, alignment) in the object. Since JButton is a subclass of AbstractButton , the property values of AbstractButton have to be stored as well as the properties of all the superclasses of AbstractButton . If a property is of an object type (e.g., background of the Color type), storing it requires storing all the property values inside this object. As you can see, this is a very tedious process. Fortunately, you don't have to go through it manually. Java provides a built-in mechanism to automate the process of writing objects. This process is referred to as object serialization , which is implemented in ObjectOutputStream . In contrast, the process of reading objects is referred to as object deserialization , which is implemented in ObjectInputStream .

Many classes in the Java API implement Serializable . The utility classes, such as java.util.Date , and all the Swing GUI component classes implement Serializable . Attempting to store an object that does not support the Serializable interface would cause a NotSerializableException .

When a serializable object is stored, the class of the object is encoded; this includes the class name and the signature of the class, the values of the object's instance variables, and the closure of any other objects referenced from the initial object. The values of the object's static variables are not stored.

Note

If an object is an instance of Serializable but contains nonserializable instance data fields, can it be serialized? The answer is no. To enable the object to be serialized, mark these data fields with the transient keyword to tell the JVM to ignore them when writing the object to an object stream. Consider the following class:

   public class   Foo   implements   java.io.Serializable {   private int   v1;   private      static      double   v2;   private    transient  A v3 =   new   A(); }   class   A { }  // A is not serializable  

When an object of the Foo class is serialized, only variable v1 is serialized. Variable v2 is not serialized because it is a static variable, and variable v3 is not serialized because it is marked transient . If v3 were not marked transient , a java.io.NotSerializable Exception would occur.


Note

If an object is written to an object stream more than once, will it be stored in multiple copies? The answer is no. When an object is written for the first time, a serial number is created for it. The JVM writes the complete content of the object along with the serial number into the object stream. After the first time, only the serial number is stored if the same object is written again. When the objects are read back, their references are the same, since only one object is actually created in the memory.


[Page 620]

18.6.2. Serializing Arrays

An array is serializable if all its elements are serializable. An entire array can be saved using writeObject into a file and later can be restored using readObject . Listing 18.6 stores an array of five int values, an array of three strings, and an array of two JButton objects, and reads them back to display on the console.

Listing 18.6. TestObjectStreamForArray.java
 1   import   java.io.*; 2   import   javax.swing.*; 3 4   public class   TestObjectStreamForArray { 5   public static void   main(String[] args) 6   throws   ClassNotFoundException, IOException { 7   int   [] numbers = {   1   ,   2   ,   3   ,   4   ,   5   }; 8 String[] strings = {   "John"   ,   "Jim"   ,   "Jake"   }; 9 JButton[] buttons = {   new   JButton(   "OK"   ),   new   JButton(   "Cancel"   )}; 10 11  // Create an output stream for file array.dat  12  ObjectOutputStream output =  13    new   ObjectOutputStream (   new   FileOutputStream(   "array.dat"   ,   true   ));  14 15  // Write arrays to the object output stream  16  output.writeObject(numbers);  17  output.writeObject(strings);  18  output.writeObject(buttons);  19 20  // Close the stream  21 output.close(); 22 23  // Create an input stream for file array.dat  24  ObjectInputStream input =  25    new   ObjectInputStream(   new   FileInputStream(   "array.dat"   ));  26 27    int   [] newNumbers = (   int   [])(input.readObject());  28  String[] newStrings = (String[])(input.readObject());  29  JButton[] newButtons = (JButton[])(input.readObject());  30 31  // Display arrays  32   for   (   int   i =     ; i < newNumbers.length; i++) 33 System.out.print(newNumbers[i] +   " "   ); 34 System.out.println(); 35 36   for   (   int   i =     ; i < newStrings.length; i++) 37 System.out.print(newStrings[i] +   " "   ); 38 System.out.println(); 39 40   for   (   int   i =     ; i < newButtons.length; i++) 41 System.out.print(newButtons[i].getText() +   " "   ); 42 } 43 } 

Lines 16 “18 write three arrays into file array.dat . Lines 27 “29 read three arrays back in the same order they were written. Since readObject() returns Object , casting is used to cast the objects into int[] , String[] , and JButton[] .

 


Introduction to Java Programming-Comprehensive Version
Introduction to Java Programming-Comprehensive Version (6th Edition)
ISBN: B000ONFLUM
EAN: N/A
Year: 2004
Pages: 503

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net