Java Reference
In-Depth Information
Although the previous code fragment works perfectly well, it does not result in a stream that is partic-
ularly efficient because the output stream returned by newOutputStream() is unbuffered, so each output
operation writes directly to the file. In practice you probably want to buffer write operations to the file in
memory, in which case you would create the ObjectOutputStream object between the try block paren-
theses like this:
try(ObjectOutputStream objectOut =
new ObjectOutputStream(new BufferedOutputStream(
Files.newOutputStream(file)))) {
...
} catch(IOException e) {
e.printStackTrace();
}
The BufferedOutputStream constructor creates an object that buffers the OutputStream object that is
passed to it, so here you get a buffered OutputStream object for the file that you pass to the ObjectOut-
putStream constructor. The BufferedOutputStream object writes the data to an internal buffer. Data from
the buffer is written to the file whenever the buffer is full, or when the stream is closed. By default, the buffer
has a capacity of 2048 bytes. If you want to use a buffer of a different size, you can use the BufferedOut-
putStream constructor that accepts a second argument of type int that defines the size of the buffer in
bytes.
To write an object to the file, you call the writeObject() method for objectOut with a reference to
the object to be written as the argument. Because this method accepts a reference of type Object as an ar-
gument, you can pass a reference of any class type to the method and this includes enum types and arrays.
Three basic conditions have to be met for an object to be written to a stream:
• The class must be declared as public .
• The class must implement the Serializable interface.
• If the class has a direct or indirect base class that is not serializable, then that base class must have
a default constructor — that is, a constructor that requires no arguments. The derived class must
take care of transferring the base class data members to the stream. I'll explain how a little later in
this chapter.
It is also very desirable that the class defines a member of type long with the name serialVersionUID .
For example, you could define the member of the class like this:
private static final long serialVersionUID = 9002L;
This defines the member as private , but any access modifier is acceptable. This variable identifies a
version number for the class that is used to verify that the same class definition is used during the deserializ-
ation process when objects are read from the file as when objects were written to the file. The specific value
you assign to the serialVersionUID variable is not important. What is important is that you change the
value if you modify the class definition, which ensures that using the incorrect version of the class to read
objects from a file is flagged. Other than this, implementing the Serializable interface is a lot less difficult
than it sounds; you see how in a moment. I come back to the question of how to deal with a non-serializable
base class later in this chapter.
If myObject is an instance of a public class that implements Serializable , then to write myObject to
the stream that you defined previously, you use the following statement:
Search WWH ::




Custom Search