?? appenda.htm
字號:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<!--
This document was converted from RTF source:
By rtftohtml 4.19
See http://www.sunpack.com/RTF
Filename:TIJ2.rtf
Application Directory:C:\TOOLS\RTF2HTML\
Subject:
Author:Bruce Eckel
Operator:Bruce Eckel
Document Comments:
Version Comments:
Comments:
Keywords:
Translation Date:05/21/2001
Translation Time:10:39:33
Translation Platform:Win32
Number of Output files:23
This File:AppendA.htm
SplitDepth=1
SkipNavPanel=1
SkipLeadingToc=1
SkipTrailingToc=1
GenContents=1
GenFrames=1
GenIndex=1
-->
<HEAD lang="en"><META http-equiv="Content-Type" content="text/html">
<TITLE>A: Passing & Returning Objects</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF"><DIV ALIGN="CENTER">
<a href="http://www.MindView.net">
<img src="mindview.gif" alt="MindView Inc." BORDER = "0"></a>
<CENTER>
<FONT FACE="Verdana" size = "-1">
[ <a href="README.txt">Viewing Hints</a> ]
[ <a href="RevHist.htm">Revision History</a> ]
[ <a href="http://www.mindview.net/Books/TIJ/">Book Home Page</a> ]
[ <a href="http://www.mindview.net/Etc/MailingList.html">Free Newsletter</a> ] <br>
[ <a href="http://www.mindview.net/Seminars">Seminars</a> ]
[ <a href="http://www.mindview.net/CDs">Seminars on CD ROM</a> ]
[ <a href="http://www.mindview.net/Services">Consulting</a> ]
</FONT>
<H2><FONT FACE="Verdana">
Thinking in Java, 2nd edition, Revision 12</FONT></H2>
<H3><FONT FACE="Verdana">©2000 by Bruce Eckel</FONT></H3>
<FONT FACE="Verdana" size = "-1">
[ <a href="Chap15.htm">Previous Chapter</a> ]
[ <a href="SimpCont.htm">Short TOC</a> ]
[ <a href="Contents.htm">Table of Contents</a> ]
[ <a href="DocIdx.htm">Index</a> ]
[ <a href="AppendB.htm">Next Chapter</a> ]
</FONT>
</CENTER>
</P></DIV><A NAME="Appendix_A"></A><A NAME="_Toc375545505"></A><A NAME="_Toc375545421"></A><A NAME="_Toc477690736"></A><A NAME="_Toc481064923"></A><A NAME="Heading599"></A><FONT FACE = "Verdana"><H1 ALIGN="LEFT">
A: Passing & Returning Objects</H1></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia" SIZE=4><backtalk:display ID=TIJ3_APPENDIXA_I0>
By now
you should be reasonably comfortable with the idea that when you’re
“passing” an object, you’re actually passing a
reference.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In many programming languages you can use
that language’s “regular” way to pass objects around, and most
of the time everything works fine. But it always seems that there comes a point
at which you must do something irregular and suddenly things get a bit more
complicated (or in the case of C++, quite complicated). Java is no exception,
and it’s important that you understand exactly what’s happening as
you pass objects around and manipulate them. This appendix will provide that
insight.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I0'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_APPENDIXA_I1>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Another way to pose the question of this
appendix, if you’re coming from a programming language so equipped, is
“Does <A NAME="Index2214"></A><A NAME="Index2215"></A>Java have
pointers?” Some have claimed that pointers are hard and dangerous and
therefore bad, and since Java is all goodness and light and will lift your
earthly programming burdens, it cannot possibly contain such things. However,
it’s more accurate to say that Java has pointers; indeed, every object
identifier in Java (except for primitives) is one of these pointers, but their
use is restricted and guarded not only by the compiler but by the run-time
system. Or to put it another way, Java has pointers, but no pointer arithmetic.
These are what I’ve been calling “references,” and you can
think of them as “safety pointers,” not unlike the safety scissors
of elementary school—they aren’t sharp, so you cannot hurt yourself
without great effort, but they can sometimes be slow and tedious.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I1'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_APPENDIXA_I2>
</FONT><A NAME="_Toc375545422"></A><A NAME="_Toc481064924"></A><BR></P></DIV>
<A NAME="Heading600"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
Passing references around</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">When you pass a
<A NAME="Index2216"></A><A NAME="Index2217"></A><A NAME="Index2218"></A>reference
into a method, you’re still pointing to the same object. A simple
experiment demonstrates this:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: appendixa:PassReferences.java</font>
<font color=#009900>// Passing references around.</font>
<font color=#0000ff>public</font> <font color=#0000ff>class</font> PassReferences {
<font color=#0000ff>static</font> <font color=#0000ff>void</font> f(PassReferences h) {
System.out.println(<font color=#004488>"h inside f(): "</font> + h);
}
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
PassReferences p = <font color=#0000ff>new</font> PassReferences();
System.out.println(<font color=#004488>"p inside main(): "</font> + p);
f(p);
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The method <B>toString( )</B> is
automatically invoked in the print statements, and <B>PassReferences</B>
inherits directly from <B>Object</B> with no redefinition of
<B>toString( )</B>. Thus, <B>Object</B>’s version of
<B>toString( ) </B>is used, which prints out the class of the object
followed by the address where that object is located (not the reference, but the
actual object storage). The output looks like this:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE>p inside main(): PassReferences@1653748
h inside f(): PassReferences@1653748</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You can see that both <B>p</B> and
<B>h</B> refer to the same object. This is far more efficient than duplicating a
new <B>PassReferences</B> object just so that you can send an argument to a
method. But it brings up an important issue.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I2'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_APPENDIXA_I3>
</FONT><A NAME="_Toc375545423"></A><A NAME="_Toc481064925"></A><BR></P></DIV>
<A NAME="Heading601"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Aliasing<BR><A NAME="Index2219"></A><A NAME="Index2220"></A></H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Aliasing means that more than one
reference is tied to the same object, as in the above example. The problem with
aliasing occurs when someone <I>writes</I> to that object. If the owners of the
other references aren’t expecting that object to change, they’ll be
surprised. This can be demonstrated with a simple example:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: appendixa:Alias1.java</font>
<font color=#009900>// Aliasing two references to one object.</font>
<font color=#0000ff>public</font> <font color=#0000ff>class</font> Alias1 {
<font color=#0000ff>int</font> i;
Alias1(<font color=#0000ff>int</font> ii) { i = ii; }
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
Alias1 x = <font color=#0000ff>new</font> Alias1(7);
Alias1 y = x; <font color=#009900>// Assign the reference</font>
System.out.println(<font color=#004488>"x: "</font> + x.i);
System.out.println(<font color=#004488>"y: "</font> + y.i);
System.out.println(<font color=#004488>"Incrementing x"</font>);
x.i++;
System.out.println(<font color=#004488>"x: "</font> + x.i);
System.out.println(<font color=#004488>"y: "</font> + y.i);
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In the line:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE>Alias1 y = x; <font color=#009900>// Assign the reference</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">a new <B>Alias1</B> reference is created,
but instead of being assigned to a fresh object created with <B>new</B>,
it’s assigned to an existing reference. So the contents of reference
<B>x</B>, which is the address of the object <B>x</B> is pointing to, is
assigned to <B>y</B>, and thus both <B>x</B> and <B>y</B> are attached to the
same object. So when <B>x</B>’s <B>i</B> is incremented in the statement:
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I3'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_APPENDIXA_I4>
</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE>x.i++;</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia"><B>y</B>’s <B>i </B>will be
affected as well. This can be seen in the output:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE>x: 7
y: 7
Incrementing x
x: 8
y: 8</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">One good solution in this case is to
simply not do it: don’t consciously alias more than one reference to an
object at the same scope. Your code will be much easier to understand and debug.
However, when you’re passing a reference in as an argument—which is
the way Java is supposed to work—you automatically alias because the local
reference that’s created can modify the “outside object” (the
object that was created outside the scope of the method). Here’s an
example:
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I4'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_APPENDIXA_I5>
</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: appendixa:Alias2.java</font>
<font color=#009900>// Method calls implicitly alias their</font>
<font color=#009900>// arguments.</font>
<font color=#0000ff>public</font> <font color=#0000ff>class</font> Alias2 {
<font color=#0000ff>int</font> i;
Alias2(<font color=#0000ff>int</font> ii) { i = ii; }
<font color=#0000ff>static</font> <font color=#0000ff>void</font> f(Alias2 reference) {
reference.i++;
}
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
Alias2 x = <font color=#0000ff>new</font> Alias2(7);
System.out.println(<font color=#004488>"x: "</font> + x.i);
System.out.println(<font color=#004488>"Calling f(x)"</font>);
f(x);
System.out.println(<font color=#004488>"x: "</font> + x.i);
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The output is:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE>x: 7
Calling f(x)
x: 8</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The method is changing its argument, the
outside object. When this kind of situation arises, you must decide whether it
makes sense, whether the user expects it, and whether it’s going to cause
problems.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXA_I5'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_APPENDIXA_I6>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In general, you call a method in order to
produce a return value and/or a change of state in the object <I>that the method
is called for</I>. (A method is how you “send a message” to that
object.) It’s much less common to call a method in order to manipulate its
arguments; this is referred to as “calling a method for its
<A NAME="Index2221"></A><I>side effects</I>.” Thus, when you create a
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -