📄 appenda.htm
字号:
method that modifies its arguments the user must be clearly instructed and
warned about the use of that method and its potential surprises. Because of the
confusion and pitfalls, it’s much better to avoid changing the argument.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I6'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_APPENDIXA_I7>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">If you need to modify an argument during
a method call and you don’t intend to modify the outside argument, then
you should protect that argument by making a copy inside your method.
That’s the subject of much of this appendix.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I7'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_APPENDIXA_I8>
</FONT><A NAME="_Toc481064926"></A><BR></P></DIV>
<A NAME="Heading602"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
Making local copies</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">To review: All argument passing in Java
is performed by passing references. That is, when you pass “an
object,” you’re really passing only a reference to an object that
lives outside the method, so if you perform any modifications with that
reference, you modify the outside object. In addition:</FONT><BR></P></DIV>
<UL>
<LI><FONT FACE="Symbol"> </FONT><FONT FACE="Georgia">Aliasing happens
automatically during argument
passing.</FONT><LI><FONT FACE="Symbol"> </FONT><FONT FACE="Georgia">There are no
local objects, only local
references.</FONT><LI><FONT FACE="Symbol"> </FONT><FONT FACE="Georgia">References
have scopes, objects do
not.</FONT><LI><FONT FACE="Symbol"> </FONT><FONT FACE="Georgia">Object lifetime
is never an issue in
Java.</FONT><LI><FONT FACE="Symbol"> </FONT><FONT FACE="Georgia">There is no
language support (e.g., “const”) to prevent objects from being
modified (that is, to prevent the negative effects of
aliasing).</FONT></UL><DIV ALIGN="LEFT"><P><FONT FACE="Georgia">If you’re
only reading information from an object and not modifying it, passing a
reference 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="fnB79" HREF="#fn79">[79]</A><FONT FACE="Georgia">. Java
does not, but it allows you to produce this effect.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I8'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_APPENDIXA_I9>
</FONT><A NAME="_Toc481064927"></A><BR></P></DIV>
<A NAME="Heading603"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Pass by value</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This brings up the terminology issue,
which always seems good for an argument. The term is
“<A NAME="Index2222"></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><BR></P></DIV>
<OL>
<LI><FONT FACE="Verdana"> </FONT><FONT FACE="Georgia">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 reference into a method, you
get a copy of the reference. Ergo, everything is pass-by-value. Of course, the
assumption is that you’re always thinking (and caring) that references 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
reference. That is, it seems to allow you to think of the reference as
“the object,” since it implicitly dereferences it whenever you make
a method call.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I9'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_APPENDIXA_I10>
</FONT><LI><FONT FACE="Verdana"> </FONT><FONT FACE="Georgia">Java
passes primitives by value (no argument there), but objects are passed by
reference. This is the world view that the reference is an alias for the object,
so you <I>don’t</I> think about passing references, 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 was
<B>byvalue</B>. (There’s no knowing, however, whether that keyword will
ever see the light of day.)
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I10'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_APPENDIXA_I11>
</FONT></OL><DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Having
given both camps a good airing, and after saying “It depends on how you
think of a reference,” I will attempt to sidestep the issue. In the end,
it isn’t <I>that</I> important—what is important is that you
understand that passing a reference allows the caller’s object to be
changed unexpectedly.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I11'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_APPENDIXA_I12>
</FONT><A NAME="_Toc375545425"></A><A NAME="_Toc481064928"></A><BR></P></DIV>
<A NAME="Heading604"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Cloning objects</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">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 <B>clone( )</B> method to
perform the operation. This is a method that’s defined as <B>protected
</B>in the base class <B>Object</B>, and which you must override as <B>public
</B>in any derived classes that you want to clone. For example, the standard
library class <B>ArrayList</B> overrides <B>clone( )</B>, so we can call
<B>clone( )</B> for <B>ArrayList</B>:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: appendixa: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) {
ArrayList v = <font color=#0000ff>new</font> ArrayList();
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < 10; i++ )
v.add(<font color=#0000ff>new</font> Int(i));
System.out.println(<font color=#004488>"v: "</font> + v);
ArrayList v2 = (ArrayList)v.clone();
<font color=#009900>// Increment all v2's elements:</font>
<font color=#0000ff>for</font>(Iterator e = v2.iterator();
e.hasNext(); )
((Int)e.next()).increment();
<font color=#009900>// See if it changed v's elements:</font>
System.out.println(<font color=#004488>"v: "</font> + v);
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The <B>clone( )</B> method produces
an <B>Object</B>, which must then be recast to the proper type. This example
shows how <B>ArrayList</B>’s<B> clone( )</B> method <I>does not</I>
automatically try to clone each of the objects that the <B>ArrayList</B>
contains—the old <B>ArrayList</B> and the cloned <B>ArrayList</B> are
aliased to the same objects. This is often called a
<A NAME="Index2223"></A><A NAME="Index2224"></A><I>shallow copy,</I> since
it’s copying only the “surface” portion of an object. The
actual object consists of this “surface,” plus all the objects that
the references are pointing to, plus all the objects <I>those </I>objects are
pointing to, etc. This is often referred to as the
“<A NAME="Index2225"></A><A NAME="Index2226"></A>web of objects.”
Copying the entire mess is called a
<A NAME="Index2227"></A><A NAME="Index2228"></A><I>deep copy.</I>
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I12'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_APPENDIXA_I13>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You can see the effect of the shallow
copy in the output, where the actions performed on <B>v2 </B>affect
<B>v</B>:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><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></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Not trying to <B>clone( ) </B>the
objects contained in the <B>ArrayList </B>is probably a fair assumption because
there’s no guarantee that those objects <I>are</I>
cloneable</FONT><A NAME="fnB80" HREF="#fn80">[80]</A><FONT FACE="Georgia">.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I13'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_APPENDIXA_I14>
</FONT><A NAME="_Toc375545426"></A><A NAME="_Toc481064929"></A><BR></P></DIV>
<A NAME="Heading605"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Adding cloneability to a class</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Even though the clone method is defined
in the base-of-all-classes <B>Object</B>, cloning is <I>not </I>automatically
available in every
class</FONT><A NAME="fnB81" HREF="#fn81">[81]</A><FONT FACE="Georgia">. This
would seem to be counterintuitive to the idea that base-class methods are always
available in derived classes. Cloning in Java goes against this idea; if you
want it to exist for a class, you must specifically add code to make cloning
work.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I14'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_APPENDIXA_I15>
</FONT><BR></P></DIV>
<A NAME="Heading606"></A><FONT FACE = "Verdana"><H4 ALIGN="LEFT">
Using a trick with protected</H4></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">To prevent default cloneability in every
class you create, the
<A NAME="Index2229"></A><A NAME="Index2230"></A><B>clone( )</B> method is
<B>protected</B> in the base class <B>Object</B>. Not only does this mean that
it’s not available by default to the client programmer who is simply using
the class (not subclassing it), but it also means that you cannot call
<B>clone( )</B> via a reference to the base class. (Although that might
seem to be useful in some situations, such as to polymorphically clone a bunch
of <B>Object</B>s.) It is in effect a way to give you, at compile-time, the
information that your object is not cloneable—and oddly enough most
classes in the standard Java library are not cloneable. Thus, if you
say:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE> Integer x = <font color=#0000ff>new</font> Integer(1);
x = x.clone();</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You will get, at compile-time, an error
message that says <B>clone( ) </B>is not accessible (since <B>Integer</B>
doesn’t override it and it defaults to the <B>protected</B> version).
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I15'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_APPENDIXA_I16>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">If, however, you’re in a class
derived from <B>Object </B>(as all classes are), then you have permission to
call <B>Object.clone( ) </B>because it’s
<A NAME="Index2231"></A><B>protected </B>and you’re an inheritor. The base
class <B>clone( ) </B>has useful functionality—it performs the actual
bitwise duplication <I>of the derived-class object</I>, thus acting as the
common cloning operation. However, you then need to make <I>your</I> clone
operation <B>public</B> for it to be accessible. <A NAME="Index2232"></A>So, two
key issues when you clone are:
</backtalk:display>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -