📄 tij0116.html
字号:
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Worm</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
point of all this was to make something reasonably complex that couldn’t
easily be serialized. The act of serializing, however, is quite simple. Once the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ObjectOutputStream</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is created from some other stream,
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>writeObject( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
serializes the object. Notice the call to
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>writeObject( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
for a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
as well. You can also write all the primitive data types using the same methods
as
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>DataOutputStream</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
(they share the same interface).
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">There
are two separate
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>try</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
blocks that look similar. The first writes and reads a file and the second, for
variety, writes and reads a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ByteArray</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
You can read and write an object using serialization to any
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>DataInputStream</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
or
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>DataOutputStream</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
including, as you will see in the networking chapter, a network. The output
from one run was:
</FONT><P></DIV>
<font color="#990000"><PRE>Worm constructor: 6
Worm constructor: 5
Worm constructor: 4
Worm constructor: 3
Worm constructor: 2
Worm constructor: 1
w = :a(262):b(100):c(396):d(480):e(316):f(398)
Worm storage, w2 = :a(262):b(100):c(396):d(480):e(316):f(398)
Worm storage, w3 = :a(262):b(100):c(396):d(480):e(316):f(398) </PRE></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">You
can see that the deserialized object really does contain all of the links that
were in the original object.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Note
that no constructor, not even the default constructor, is called in the process
of deserializing a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Serializable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object. The entire object is restored by recovering data from the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>InputStream</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Object
serialization is another Java 1.1<A NAME="Index1320"></A>
feature that is not part of the new
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Reader</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Writer</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
hierarchies, but instead uses the old
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>InputStream</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>OutputStream</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
hierarchies. Thus you might encounter situations in which you’re forced
to mix the two hierarchies.
</FONT><a name="_Toc408018639"></a><P></DIV>
<A NAME="Heading344"></A><H3 ALIGN=LEFT>
Finding
the class
</H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">You
might wonder what’s necessary for an object to be recovered from its
serialized state. For example, suppose you serialize an object and send it as a
file or through a network to another machine. Could a program on the other
machine reconstruct the object using only the contents of the file?
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
best way to answer this question is (as usual) by performing an experiment. The
following file goes in the subdirectory for this chapter:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: Alien.java</font>
<font color="#009900">// A serializable class</font>
<font color="#0000ff">import</font> java.io.*;
<font color="#0000ff">public</font> <font color="#0000ff">class</font> Alien <font color="#0000ff">implements</font> Serializable {
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
file that creates and serializes an
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Alien
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">object
goes in the same directory:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: FreezeAlien.java</font>
<font color="#009900">// Create a serialized output file</font>
<font color="#0000ff">import</font> java.io.*;
<font color="#0000ff">public</font> <font color="#0000ff">class</font> FreezeAlien {
<font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args)
<font color="#0000ff">throws</font> Exception {
ObjectOutput out =
<font color="#0000ff">new</font> ObjectOutputStream(
<font color="#0000ff">new</font> FileOutputStream("file.x"));
Alien zorcon = <font color="#0000ff">new</font> Alien();
out.writeObject(zorcon);
}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Rather
than catching and handling exceptions, this program takes the quick and dirty
approach of passing the exceptions out of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>main( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
so they’ll be reported on the command line.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Once
the program is compiled and run, copy the resulting
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>file.x</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to a subdirectory called
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>xfiles</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
where the following code goes:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: ThawAlien.java</font>
<font color="#009900">// Try to recover a serialized file without the </font>
<font color="#009900">// class of object that's stored in that file.</font>
<font color="#0000ff">package</font> c10.xfiles;
<font color="#0000ff">import</font> java.io.*;
<font color="#0000ff">public</font> <font color="#0000ff">class</font> ThawAlien {
<font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args)
<font color="#0000ff">throws</font> Exception {
ObjectInputStream in =
<font color="#0000ff">new</font> ObjectInputStream(
<font color="#0000ff">new</font> FileInputStream("file.x"));
Object mystery = in.readObject();
System.out.println(
mystery.getClass().toString());
}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">This
program opens the file and reads in the object
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>mystery</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
successfully. However, as soon as you try to find out anything about the object
– which requires the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Class</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object for
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Alien</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
– the Java Virtual Machine (JVM) cannot find
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Alien.class</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
(unless it happens to be in the Classpath, which it shouldn’t be in this
example). You’ll get a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ClassNotFoundException.</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
(Once again, all evidence of alien life vanishes before proof of its existence
can be verified!)
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">If
you expect to do much after you’ve recovered an object that has been
serialized, you must make sure that the JVM can find the associated
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>.class</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
file either in the local class path or somewhere on the Internet.
</FONT><a name="_Toc408018640"></a><P></DIV>
<A NAME="Heading345"></A><H3 ALIGN=LEFT>
Controlling
serialization
</H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">As
you can see, the default serialization mechanism is trivial to use. But what if
you have special needs? Perhaps you have special security issues and you
don’t want to serialize portions of your object, or perhaps it just
doesn’t make sense for one sub-object to be serialized if that part needs
to be created anew when the object is recovered.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">You
can <A NAME="Index1321"></A><A NAME="Index1322"></A>control
the process of serialization by implementing the <A NAME="Index1323"></A><A NAME="Index1324"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Externalizable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
interface instead of the <A NAME="Index1325"></A><A NAME="Index1326"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Serializable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
interface. The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Externalizable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
interface extends the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Serializable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
interface and adds two methods, <A NAME="Index1327"></A><A NAME="Index1328"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>writeExternal( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and <A NAME="Index1329"></A><A NAME="Index1330"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>readExternal( ),</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
that
<a name="which"></a>
are automatically called for your object during serialization and
deserialization so that you can perform your special operations.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
following example shows simple implementations of the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Externalizable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
interface methods. Note that
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Blip1</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Blip2</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
are nearly identical except for a subtle difference (see if you can discover it
by looking at the code):
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: Blips.java</font>
<font color="#009900">// Simple use of Externalizable & a pitfall</font>
<font color="#0000ff">import</font> java.io.*;
<font color="#0000ff">import</font> java.util.*;
<font color="#0000ff">class</font> Blip1 <font color="#0000ff">implements</font> Externalizable {
<font color="#0000ff">public</font> Blip1() {
System.out.println("Blip1 Constructor");
}
<font color="#0000ff">public</font> <font color="#0000ff">void</font> writeExternal(ObjectOutput out)
<font color="#0000ff">throws</font> IOException {
System.out.println("Blip1.writeExternal");
}
<font color="#0000ff">public</font> <font color="#0000ff">void</font> readExternal(ObjectInput in)
<font color="#0000ff">throws</font> IOException, ClassNotFoundException {
System.out.println("Blip1.readExternal");
}
}
<font color="#0000ff">class</font> Blip2 <font color="#0000ff">implements</font> Externalizable {
Blip2() {
System.out.println("Blip2 Constructor");
}
<font color="#0000ff">public</font> <font color="#0000ff">void</font> writeExternal(ObjectOutput out)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -