📄 tij0116.html
字号:
sensitive information that you don’t want to serialize, such as a
password. Even if that information is
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>private
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">in
the object, once it’s serialized it’s possible for someone to
access it by reading a file or intercepting a network transmission.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">One
way to prevent sensitive parts of your object from being serialized is to
implement your class as
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Externalizable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
as shown previously. Then nothing is automatically serialized and you can
explicitly serialize only the necessary parts inside
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>writeExternal( )</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">If
you’re working with 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,
however, all serialization happens automatically. To control this, you can turn
off serialization on a field-by-field basis using the <A NAME="Index1331"></A><A NAME="Index1332"></A><A NAME="Index1333"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>transient</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword, which says “Don’t bother saving or restoring this –
I’ll take care of it.”
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">For
example, consider a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Login
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">object
that keeps information about a particular login session. Suppose that, once you
verify the login, you want to store the data, but without the password. The
easiest way to do this is by implementing <A NAME="Index1334"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Serializable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and marking the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>password</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
field as
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>transient</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
Here’s what it looks like:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: Logon.java</font>
<font color="#009900">// Demonstrates the "transient" keyword</font>
<font color="#0000ff">import</font> java.io.*;
<font color="#0000ff">import</font> java.util.*;
<font color="#0000ff">class</font> Logon <font color="#0000ff">implements</font> Serializable {
<font color="#0000ff">private</font> Date date = <font color="#0000ff">new</font> Date();
<font color="#0000ff">private</font> String username;
<font color="#0000ff">private</font> <font color="#0000ff">transient</font> String password;
Logon(String name, String pwd) {
username = name;
password = pwd;
}
<font color="#0000ff">public</font> String toString() {
String pwd =
(password == <font color="#0000ff">null</font>) ? "(n/a)" : password;
<font color="#0000ff">return</font> "logon info: \n " +
"username: " + username +
"\n date: " + date.toString() +
"\n password: " + pwd;
}
<font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
Logon a = <font color="#0000ff">new</font> Logon("Hulk", "myLittlePony");
System.out.println( "logon a = " + a);
<font color="#0000ff">try</font> {
ObjectOutputStream o =
<font color="#0000ff">new</font> ObjectOutputStream(
<font color="#0000ff">new</font> FileOutputStream("Logon.out"));
o.writeObject(a);
o.close();
<font color="#009900">// Delay:</font>
<font color="#0000ff">int</font> seconds = 5;
<font color="#0000ff">long</font> t = System.currentTimeMillis()
+ seconds * 1000;
<font color="#0000ff">while</font>(System.currentTimeMillis() < t)
;
<font color="#009900">// Now get them back:</font>
ObjectInputStream in =
<font color="#0000ff">new</font> ObjectInputStream(
<font color="#0000ff">new</font> FileInputStream("Logon.out"));
System.out.println(
"Recovering object at " + <font color="#0000ff">new</font> Date());
a = (Logon)in.readObject();
System.out.println( "logon a = " + a);
} <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">You
can see that the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>date</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>username</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
fields are ordinary (not
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>transient</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">),
and thus are automatically serialized. However, the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>password</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>transient</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
and so is not stored to disk; also the serialization mechanism makes no attempt
to recover it. The output is:
</FONT><P></DIV>
<font color="#990000"><PRE>logon a = logon info:
username: Hulk
date: Sun Mar 23 18:25:53 PST 1997
password: myLittlePony
Recovering object at Sun Mar 23 18:25:59 PST 1997
logon a = logon info:
username: Hulk
date: Sun Mar 23 18:25:53 PST 1997
password: (n/a) </PRE></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">When
the object is recovered, the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>password</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
field is
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>null</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
Note that
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>toString( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
must check for a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>null</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
value of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>password
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">because
if you try to assemble a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object using the overloaded ‘
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>+</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">’
operator, and that operator encounters a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>null</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
handle, you’ll get a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>NullPointerException.</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
(Newer versions of Java might contain code to avoid this problem.)
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">You
can also see that the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>date</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
field is stored to and recovered from disk and not generated anew.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Since
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Externalizable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
objects do not store any of their fields by default, the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>transient</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword is for use with
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Serializable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
objects only.
</FONT><P></DIV>
<A NAME="Heading347"></A><H4 ALIGN=LEFT>
An
alternative to Externalizable
</H4>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">If
you’re not keen on implementing the <A NAME="Index1335"></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,
there’s another approach. You can implement 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
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>add
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">(notice
I say “add” and not “override” or
“implement”) methods called <A NAME="Index1336"></A><A NAME="Index1337"></A></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="Index1338"></A><A NAME="Index1339"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>readObject( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
that will automatically be called when the object is serialized and
deserialized, respectively. That is, if you provide these two methods they will
be used instead of the default serialization.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
methods must have these exact signatures:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#0000ff">private</font> <font color="#0000ff">void</font>
writeObject(ObjectOutputStream stream)
<font color="#0000ff">throws</font> IOException;
<font color="#0000ff">private</font> <font color="#0000ff">void</font>
readObject(ObjectInputStream stream)
<font color="#0000ff">throws</font> IOException, ClassNotFoundException </PRE></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">From
a design standpoint, things get really weird here. First of all, you might
think that because these methods are not part of a base class or 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, they ought to be defined in their own interface(s). But notice that
they are defined as
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>private</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
which means they are to be called only by other members of this class. However,
you don’t actually call them from other members of this class, but
instead the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>writeObject( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>readObject( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
methods of the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ObjectOutputStream</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ObjectInputStream</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
objects call your object’s
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>writeObject( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>readObject( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
methods. (Notice my tremendous restraint in not launching into a long diatribe
about using the same method names here. In a word: confusing.) You might wonder
how the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ObjectOutputStream</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ObjectInputStream</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
objects have access to
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>private</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
methods of your class. We can only assume that this is part of the
serialization magic.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">In
any event, anything defined in an
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interface</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is automatically
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>public</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
so if
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>writeObject( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -