📄 tij0116.html
字号:
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>readObject( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
must be
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>private</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
then they can’t be part of an
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interface</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
Since you must follow the signatures exactly, the effect is the same as if
you’re implementing an
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interface</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">It
would appear that when you call
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ObjectOutputStream.writeObject( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Serializable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object that you pass it to is interrogated (using reflection, no doubt) to see
if it implements its own
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>writeObject( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
If so, the normal serialization process is skipped and the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>writeObject( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is called. The same sort of situation exists for
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>readObject( )</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">There’s
one other twist. Inside your
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>writeObject( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
you can choose to perform the default
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>writeObject( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
action by calling
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>defaultWriteObject( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
Likewise, inside
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>readObject( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
you can call
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>defaultReadObject( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
Here is a simple example that demonstrates how you can control the storage and
retrieval of 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:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: SerialCtl.java</font>
<font color="#009900">// Controlling serialization by adding your own</font>
<font color="#009900">// writeObject() and readObject() methods.</font>
<font color="#0000ff">import</font> java.io.*;
<font color="#0000ff">public</font> <font color="#0000ff">class</font> SerialCtl <font color="#0000ff">implements</font> Serializable {
String a;
<font color="#0000ff">transient</font> String b;
<font color="#0000ff">public</font> SerialCtl(String aa, String bb) {
a = "Not Transient: " + aa;
b = "Transient: " + bb;
}
<font color="#0000ff">public</font> String toString() {
<font color="#0000ff">return</font> a + "\n" + b;
}
<font color="#0000ff">private</font> <font color="#0000ff">void</font>
writeObject(ObjectOutputStream stream)
<font color="#0000ff">throws</font> IOException {
stream.defaultWriteObject();
stream.writeObject(b);
}
<font color="#0000ff">private</font> <font color="#0000ff">void</font>
readObject(ObjectInputStream stream)
<font color="#0000ff">throws</font> IOException, ClassNotFoundException {
stream.defaultReadObject();
b = (String)stream.readObject();
}
<font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
SerialCtl sc =
<font color="#0000ff">new</font> SerialCtl("Test1", "Test2");
System.out.println("Before:\n" + sc);
ByteArrayOutputStream buf =
<font color="#0000ff">new</font> ByteArrayOutputStream();
<font color="#0000ff">try</font> {
ObjectOutputStream o =
<font color="#0000ff">new</font> ObjectOutputStream(buf);
o.writeObject(sc);
<font color="#009900">// Now get it back:</font>
ObjectInputStream in =
<font color="#0000ff">new</font> ObjectInputStream(
<font color="#0000ff">new</font> ByteArrayInputStream(
buf.toByteArray()));
SerialCtl sc2 = (SerialCtl)in.readObject();
System.out.println("After:\n" + sc2);
} <font color="#0000ff">catch</font>(Exception e) {
e.printStackTrace();
}
}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">In
this example, one
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
field is ordinary and the other is
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>transient</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
to prove that the non-
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>transient</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
field is saved by the <A NAME="Index1340"></A><A NAME="Index1341"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>defaultWriteObject( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method and the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>transient</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
field is saved and restored explicitly. The fields are initialized inside the
constructor rather than at the point of definition to prove that they are not
being initialized by some automatic mechanism during deserialization.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">If
you are going to use the default mechanism to write the non-
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>transient</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
parts of your object, you must call
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>defaultWriteObject( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
as the first operation in
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>writeObject( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and <A NAME="Index1342"></A><A NAME="Index1343"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>defaultReadObject( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
as the first operation in
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>readObject( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
These are strange method calls. It would appear, for example, that you are
calling
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>defaultWriteObject( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
for an
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ObjectOutputStream</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and passing it no arguments, and yet it somehow turns around and knows the
handle to your object and how to write all the non-
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>transient</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
parts. Spooky.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
storage and retrieval of the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>transient</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
objects uses more familiar code. And yet, think about what happens here. In
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>main( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>SerialCtl</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object is created, and then it’s serialized to an
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ObjectOutputStream.</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
(Notice in this case that a buffer is used instead of a file – it’s
all the same to the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ObjectOutputStream.</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">)
The serialization occurs in the line:
</FONT><P></DIV><DIV ALIGN=LEFT><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">o.writeObject(sc);</FONT></TT><P></DIV><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>writeObject( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method must be examining
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>sc</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to see if it has its own
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>writeObject( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method. (Not by checking the interface – there isn’t one – or
the class type, but by actually hunting for the method using reflection.) If it
does, it uses that. A similar approach holds true for
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>readObject( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
Perhaps this was the only practical way that they could solve the problem, but
it’s certainly strange.
</FONT><P></DIV>
<A NAME="Heading348"></A><H4 ALIGN=LEFT>
Versioning<P><A NAME="Index1344"></A><A NAME="Index1345"></A></H4>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">It’s
possible that you might want to change the version of a serializable class
(objects of the original class might be stored in a database, for example).
This is supported but you’ll probably do it only in special cases, and it
requires an extra depth of understanding that we will not attempt to achieve
here. The JDK1.1 HTML documents downloadable from Sun (which might be part of
your Java package’s online documents) cover this topic quite thoroughly.
</FONT><a name="_Toc408018641"></a><P></DIV>
<A NAME="Heading349"></A><H3 ALIGN=LEFT>
Using
persistence
<P><A NAME="Index1346"></A></H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">It’s
quite appealing to use <A NAME="Index1347"></A>serialization
technology to store some of the state of your program so that you can easily
restore the program to the current state later. But before you can do this,
some questions must be answered. What happens if you serialize two objects that
both have a handle to a third object? When you restore those two objects from
their serialized state, do you get only one occurrence of the third object?
What if you serialize your two objects to separate files and deserialize them
in different parts of your code?
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Here’s
an example that shows the problem:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: MyWorld.java</font>
<font color="#0000ff">import</font> java.io.*;
<font color="#0000ff">import</font> java.util.*;
<font color="#0000ff">class</font> House <font color="#0000ff">implements</font> Serializable {}
<font color="#0000ff">class</font> Animal <font color="#0000ff">implements</font> Serializable {
String name;
House preferredHouse;
Animal(String nm, House h) {
name = nm;
preferredHouse = h;
}
<font color="#0000ff">public</font> String toString() {
<font color="#0000ff">return</font> name + "[" + <font color="#0000ff">super</font>.toString() +
"], " + preferredHouse + "\n";
}
}
<font color="#0000ff">public</font> <font color="#0000ff">class</font> MyWorld {
<font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
House house = <font color="#0000ff">new</font> House();
Vector animals = <font color="#0000ff">new</font> Vector();
animals.addElement(
<font color="#0000ff">new</font> Animal("Bosco the dog", house));
animals.addElement(
<font color="#0000ff">new</font> Animal("Ralph the hamster", house));
animals.addElement(
<font color="#0000ff">new</font> Animal("Fronk the cat", house));
System.out.println("animals: " + animals);
<font color="#0000ff">try</font> {
ByteArrayOutputStream buf1 =
<font color="#0000ff">new</font> ByteArrayOutputStream();
Obj
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -