📄 tij0127.html
字号:
<html><body>
<table width="100%"><tr>
<td>
<a href="http://www.bruceeckel.com/javabook.html">Bruce Eckel's Thinking in Java</a>
</td>
<td align="right">
<a href="tij_c.html">Contents</a> | <a href="tij0126.html">Prev</a> | <a href="tij0128.html">Next</a>
</td>
</tr></table>
<hr>
<H2 ALIGN=LEFT>
Making
local copies
</H2>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">To
review: all argument passing in Java is performed by passing handles. That is,
when you pass “an object,” you’re really passing only a
handle to an object that lives outside the method, so if you perform any
modifications with that handle, you modify the outside object. In addition:
</FONT><P></DIV>
<UL>
<LI><FONT FACE="Symbol" SIZE=3 COLOR="Black"> </FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Aliasing
happens automatically during argument passing.
</FONT><LI><FONT FACE="Symbol" SIZE=3 COLOR="Black"> </FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">There
are no local objects, only local handles.
</FONT><LI><FONT FACE="Symbol" SIZE=3 COLOR="Black"> </FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Handles
have scopes, objects do not.
</FONT><LI><FONT FACE="Symbol" SIZE=3 COLOR="Black"> </FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Object
lifetime is never an issue in Java.
</FONT><LI><FONT FACE="Symbol" SIZE=3 COLOR="Black"> </FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">There
is no language support (e.g. const) to prevent objects from being modified (to
prevent negative effects of aliasing).
</FONT></UL><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">If
you’re only reading information from an object and not modifying it,
passing a handle is the most efficient form of argument passing. This is nice;
the default way of doing things is also the most efficient. However, sometimes
it’s necessary to be able to treat the object as if it were
“local” so that changes you make affect only a local copy and do
not modify the outside object. Many programming languages support the ability
to automatically make a local copy of the outside object, inside the method.
</FONT><A NAME="fnB49" HREF="#fn49">[49]</A><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
Java does not, but it allows you to produce this effect.
</FONT><a name="_Toc408018657"></a><P></DIV>
<A NAME="Heading368"></A><H3 ALIGN=LEFT>
Pass
by value
</H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">This
brings up the terminology issue, which always seems good for an argument. The
term is “<A NAME="Index1447"></A>pass
by value,” and the meaning depends on how you perceive the operation of
the program. The general meaning is that you get a local copy of whatever
you’re passing, but the real question is how you think about what
you’re passing. When it comes to the meaning of “pass by
value,” there are two fairly distinct camps:
</FONT><P></DIV>
<OL>
<LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"> Java
passes everything by value. When you’re passing primitives into a method,
you get a distinct copy of the primitive. When you’re passing a handle
into a method, you get a copy of the handle. Ergo, everything is pass by value.
Of course, the assumption is that you’re always thinking (and caring)
that handles are being passed, but it seems like the Java design has gone a
long way toward allowing you to ignore (most of the time) that you’re
working with a handle. That is, it seems to allow you to think of the handle as
“the object,” since it implicitly dereferences it whenever you make
a method call.
</FONT><LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"> Java
passes primitives by value (no argument there), but objects are passed by
reference. This is the world view that the handle is an alias for the object,
so you
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>don’t</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
think about passing handles, but instead say “I’m passing the
object.” Since you don’t get a local copy of the object when you
pass it into a method, objects are clearly not passed by value. There appears
to be some support for this view within Sun, since one of the “reserved
but not implemented” keywords is
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>byvalue</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
(There’s no knowing, however, whether that keyword will ever see the
light of day.)
</FONT></OL><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Having
given both camps a good airing and after saying “It depends on how you
think of a handle,” I will attempt to sidestep the issue for the rest of
the book. In the end, it isn’t
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>that</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
important – what is important is that you understand that passing a
handle allows the caller’s object to be changed unexpectedly.
</FONT><a name="_Toc375545425"></a><a name="_Toc408018658"></a><P></DIV>
<A NAME="Heading369"></A><H3 ALIGN=LEFT>
Cloning
objects
</H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
most likely reason for making a local copy of an object is if you’re
going to modify that object and you don’t want to modify the
caller’s object. If you decide that you want to make a local copy, you
simply use the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>clone( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method to perform the operation. This is a method that’s defined as
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>protected
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">in
the base class
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Object</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and which you must override as
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>public
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">in
any derived classes that you want to clone. For example, the standard library
class
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
overrides
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>clone( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
so we can call
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>clone( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
for
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">:</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: Cloning.java</font>
<font color="#009900">// The clone() operation works for only a few</font>
<font color="#009900">// items in the standard Java library.</font>
<font color="#0000ff">import</font> java.util.*;
<font color="#0000ff">class</font> Int {
<font color="#0000ff">private</font> <font color="#0000ff">int</font> i;
<font color="#0000ff">public</font> Int(<font color="#0000ff">int</font> ii) { i = ii; }
<font color="#0000ff">public</font> <font color="#0000ff">void</font> increment() { i++; }
<font color="#0000ff">public</font> String toString() {
<font color="#0000ff">return</font> Integer.toString(i);
}
}
<font color="#0000ff">public</font> <font color="#0000ff">class</font> Cloning {
<font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
Vector v = <font color="#0000ff">new</font> Vector();
<font color="#0000ff">for</font>(<font color="#0000ff">int</font> i = 0; i < 10; i++ )
v.addElement(<font color="#0000ff">new</font> Int(i));
System.out.println("v: " + v);
Vector v2 = (Vector)v.clone();
<font color="#009900">// Increment all v2's elements:</font>
<font color="#0000ff">for</font>(Enumeration e = v2.elements();
e.hasMoreElements(); )
((Int)e.nextElement()).increment();
<font color="#009900">// See if it changed v's elements:</font>
System.out.println("v: " + v);
}
} <font color="#009900">///:~ </PRE></font></font><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>clone( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method produces an
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Object</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
which must then be recast to the proper type. This example shows how
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">’s</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>
clone( )
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>does
not
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
automatically try to clone each of the objects that the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
contains – the old
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and the cloned
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
are aliased to the same objects. This is often called a <A NAME="Index1448"></A><A NAME="Index1449"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>shallow
copy
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
since it’s copying only the “surface” portion of an object.
The actual object consists of this “surface” plus all the objects
that the handles are pointing to, plus all the objects
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>those
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">objects
are pointing to, etc. This is often referred to as the “<A NAME="Index1450"></A><A NAME="Index1451"></A>web
of objects.” Copying the entire mess is called a <A NAME="Index1452"></A><A NAME="Index1453"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>deep
copy
</I></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">You
can see the effect of the shallow copy in the output, where the actions
performed on
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>v2
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">affect
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>v</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">:</FONT><P></DIV>
<font color="#990000"><PRE>v: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
v: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] </PRE></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Not
trying to
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>clone( )
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">the
objects contained in the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Vector
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">is
probably a fair assumption because there’s no guarantee that those objects
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>are</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
cloneable.
</FONT><A NAME="fnB50" HREF="#fn50">[50]</A><a name="_Toc375545426"></a><a name="_Toc408018659"></a><P></DIV>
<A NAME="Heading370"></A><H3 ALIGN=LEFT>
Adding
cloneability to a class
</H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Even
though the clone method is defined in the base-of-all-classes
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Object</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
cloning is
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>not
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">automatically
available in every class.
</FONT><A NAME="fnB51" HREF="#fn51">[51]</A><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
This would seem to be counterintuitive to the idea that base-class methods are
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -