📄 tij0116.html
字号:
<font color="#0000ff">throws</font> IOException {
System.out.println("Blip2.writeExternal");
}
<font color="#0000ff">public</font> <font color="#0000ff">void</font> readExternal(ObjectInput in)
<font color="#0000ff">throws</font> IOException, ClassNotFoundException {
System.out.println("Blip2.readExternal");
}
}
<font color="#0000ff">public</font> <font color="#0000ff">class</font> Blips {
<font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
System.out.println("Constructing objects:");
Blip1 b1 = <font color="#0000ff">new</font> Blip1();
Blip2 b2 = <font color="#0000ff">new</font> Blip2();
<font color="#0000ff">try</font> {
ObjectOutputStream o =
<font color="#0000ff">new</font> ObjectOutputStream(
<font color="#0000ff">new</font> FileOutputStream("Blips.out"));
System.out.println("Saving objects:");
o.writeObject(b1);
o.writeObject(b2);
o.close();
<font color="#009900">// Now get them back:</font>
ObjectInputStream in =
<font color="#0000ff">new</font> ObjectInputStream(
<font color="#0000ff">new</font> FileInputStream("Blips.out"));
System.out.println("Recovering b1:");
b1 = (Blip1)in.readObject();
<font color="#009900">// OOPS! Throws an exception:</font>
<font color="#009900">//! System.out.println("Recovering b2:");</font>
<font color="#009900">//! b2 = (Blip2)in.readObject();</font>
} <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">The
output for this program is:
</FONT><P></DIV>
<font color="#990000"><PRE>Constructing objects:
Blip1 Constructor
Blip2 Constructor
Saving objects:
Blip1.writeExternal
Blip2.writeExternal
Recovering b1:
Blip1 Constructor
Blip1.readExternal</PRE></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
reason that the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Blip2</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object is not recovered is that trying to do so causes an exception. Can you
see the difference between
</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">?
The constructor for
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Blip1</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>public</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
while the constructor for
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Blip2</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is not, and that causes the exception upon recovery. Try making
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Blip2</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">’s
constructor
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>public
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">and
removing the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>//!
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">comments
to see the correct results.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">When
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>b1</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is recovered, the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Blip1</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
default constructor is called. This is different from recovering 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, in which the object is constructed entirely from its stored bits, with
no constructor calls. With an
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Externalizable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object, all the normal default construction behavior occurs (including the
initializations at the point of field definition), and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>then</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>readExternal( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is called. You need to be aware of this – in particular the fact that all
the default construction always takes place – to produce the correct
behavior in your
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Externalizable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
objects.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Here’s
an example that shows what you must do to fully store and retrieve an
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Externalizable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: Blip3.java</font>
<font color="#009900">// Reconstructing an externalizable object</font>
<font color="#0000ff">import</font> java.io.*;
<font color="#0000ff">import</font> java.util.*;
<font color="#0000ff">class</font> Blip3 <font color="#0000ff">implements</font> Externalizable {
<font color="#0000ff">int</font> i;
String s; <font color="#009900">// No initialization</font>
<font color="#0000ff">public</font> Blip3() {
System.out.println("Blip3 Constructor");
<font color="#009900">// s, i not initialized</font>
}
<font color="#0000ff">public</font> Blip3(String x, <font color="#0000ff">int</font> a) {
System.out.println("Blip3(String x, <font color="#0000ff">int</font> a)");
s = x;
i = a;
<font color="#009900">// s & i initialized only in non-default</font>
<font color="#009900">// constructor.</font>
}
<font color="#0000ff">public</font> String toString() { <font color="#0000ff">return</font> s + i; }
<font color="#0000ff">public</font> <font color="#0000ff">void</font> writeExternal(ObjectOutput out)
<font color="#0000ff">throws</font> IOException {
System.out.println("Blip3.writeExternal");
<font color="#009900">// You must do this:</font>
out.writeObject(s); out.writeInt(i);
}
<font color="#0000ff">public</font> <font color="#0000ff">void</font> readExternal(ObjectInput in)
<font color="#0000ff">throws</font> IOException, ClassNotFoundException {
System.out.println("Blip3.readExternal");
<font color="#009900">// You must do this:</font>
s = (String)in.readObject();
i =in.readInt();
}
<font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
System.out.println("Constructing objects:");
Blip3 b3 = <font color="#0000ff">new</font> Blip3("A String ", 47);
System.out.println(b3.toString());
<font color="#0000ff">try</font> {
ObjectOutputStream o =
<font color="#0000ff">new</font> ObjectOutputStream(
<font color="#0000ff">new</font> FileOutputStream("Blip3.out"));
System.out.println("Saving object:");
o.writeObject(b3);
o.close();
<font color="#009900">// Now get it back:</font>
ObjectInputStream in =
<font color="#0000ff">new</font> ObjectInputStream(
<font color="#0000ff">new</font> FileInputStream("Blip3.out"));
System.out.println("Recovering b3:");
b3 = (Blip3)in.readObject();
System.out.println(b3.toString());
} <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">The
fields
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>s</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>i
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">are
initialized only in the second constructor, but not in the default constructor.
This means that if you don’t initialize
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>s</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>i
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">in
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>readExternal</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
it will be
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>null</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
(since the storage for the object gets wiped to zero in the first step of
object creation). If you comment out the two lines of code following the
phrases “You must do this” and run the program, you’ll see
that when the object is recovered,
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>s</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>null</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>i</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is zero.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">If
you are inheriting from an
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Externalizable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object, you’ll typically call the base-class versions of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>writeExternal( )
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>readExternal( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to provide proper storage and retrieval of the base-class components.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">So
to make things work correctly you must not only write the important data from
the object during the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>writeExternal( )
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">method
(there is no default behavior that writes any of the member objects for an
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Externalizable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object), but you must also recover that data in the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>readExternal( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method. This can be a bit confusing at first because the default construction
behavior for an
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Externalizable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object can make it seem like some kind of storage and retrieval takes place
automatically. It does not.
</FONT><P></DIV>
<A NAME="Heading346"></A><H4 ALIGN=LEFT>
The
transient keyword
</H4>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">When
you’re controlling serialization, there might be a particular subobject
that you don’t want Java’s serialization mechanism to automatically
save and restore. This is commonly the case if that subobject represents
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -