⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tij319.htm

📁 这也是我们java老师给我们的thinking in java的一些资料
💻 HTM
📖 第 1 页 / 共 5 页
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html lang="en">
<!--
This document was converted from RTF source: 
By r2net 5.8 r2netcmd Windows 
See http://www.logictran.com
-->
<head><meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Thinking in Java, 3rd ed. Revision 4.0: A: Passing &amp; Returning Objects</title>
<link rel="stylesheet" href="stylesheet.css" type="text/css"></head>

<body >
   <CENTER>     <a href="http://www.MindView.net">     <img src="mindview.gif" alt="MindView Inc." BORDER = "0"></a>     <Font FACE="Verdana, Tahoma, Arial, Helvetica, Sans">     <h2>Thinking in Java, 3<sup>rd</sup> ed. Revision 4.0</h2>     <FONT size = "-1"><br>     [ <a href="README.txt">Viewing Hints</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> ] <br><br>     </FONT></FONT>   </CENTER> 
<font face="Georgia"><div align="CENTER"><a href="TIJ318.htm" target="RightFrame"><img src="./prev.gif" alt="Previous " border="0"></a>
<a href="TIJ320.htm" target="RightFrame"><img src="./next.gif" alt="Next " border="0"></a>

<a href="TIJ3_t.htm"><img src="./first.gif" alt="Title Page " border="0"></a>
<a href="TIJ3_i.htm"><img src="./index.gif" alt="Index " border="0"></a>
<a href="TIJ3_c.htm"><img src="./contents.gif" alt="Contents " border="0"></a>
</div>
<hr>

<h1>
<a name="_Toc24272656"></a><a name="_Toc24775988"></a><a name="Heading24485"></a>A:
Passing &amp; Returning Objects</h1>
<p class="Intro">By now you should be reasonably comfortable with the idea that when you&#146;re &#147;passing&#148; an object, you&#146;re actually passing a reference.<br></p>
<p>In many programming languages you can use that language&#146;s &#147;regular&#148; 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&#146;s important that you understand exactly what&#146;s happening as you pass objects around and manipulate them. This appendix will provide that insight. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]AppendA_2700" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>Another way to pose the question of this appendix, if you&#146;re coming from a programming language so equipped, is &#147;Does Java have pointers?&#148; 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&#146;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&#146;ve been calling &#147;references,&#148; and you can think of them as &#147;safety pointers,&#148; not unlike the safety scissors of elementary school&#151;they aren&#146;t sharp, so you cannot hurt yourself without great effort, but they can sometimes be slow and tedious. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]AppendA_2701" title="Send BackTalk Comment">Feedback</a></font><br></p>
<h2>
<a name="Index2145"></a><a name="Index2146"></a><a name="_Toc375545422"></a><a name="_Toc24775989"></a><a name="Heading24489"></a>Passing
references around</h2>
<p>When you pass a reference into a method, you&#146;re still pointing to the same object. A simple experiment demonstrates this:<br></p>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: appendixa:PassReferences.java</font>
<font color=#009900>// Passing references around.</font>
<font color=#0000ff>import</font> com.bruceeckel.simpletest.*;

<font color=#0000ff>public</font> <font color=#0000ff>class</font> PassReferences {
  <font color=#0000ff>private</font> <font color=#0000ff>static</font> Test monitor = <font color=#0000ff>new</font> Test();
  <font color=#0000ff>public</font> <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);
    monitor.expect(<font color=#0000ff>new</font> String[] {
      <font color=#004488>"%% p inside main\\(\\): PassReferences@[a-z0-9]+"</font>,
      <font color=#004488>"%% h inside f\\(\\): PassReferences@[a-z0-9]+"</font>
    });
  }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE><p><br></p>
<p>The method <b>toString(&#160;)</b> is automatically invoked in the print statements, and <b>PassReferences</b> inherits directly from <b>Object</b> with no redefinition of <b>toString(&#160;)</b>. Thus, <b>Object</b>&#146;s version of <b>toString(&#160;) </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 size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]A0096" title="Send BackTalk Comment">Feedback</a></font><br></p>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE>p inside main(): PassReferences@ad3ba4
h inside f(): PassReferences@ad3ba4</PRE></FONT></BLOCKQUOTE><p><br></p>
<p>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. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]AppendA_2702" title="Send BackTalk Comment">Feedback</a></font><br></p>
<h3>
<a name="_Toc375545423"></a><a name="_Toc24775990"></a><a name="Heading24516"></a>Aliasing<br></h3>
<p><a name="Index2150"></a><a name="Index2151"></a>Aliasing means that more than one reference is tied to the same object, as in the preceding example. The problem with aliasing occurs when someone <i>writes</i> to that object. If the owners of the other references aren&#146;t expecting that object to change, they&#146;ll be surprised. This can be demonstrated with a simple example: <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]A0097" title="Send BackTalk Comment">Feedback</a></font><br></p>

<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>import</font> com.bruceeckel.simpletest.*;

<font color=#0000ff>public</font> <font color=#0000ff>class</font> Alias1 {
  <font color=#0000ff>private</font> <font color=#0000ff>static</font> Test monitor = <font color=#0000ff>new</font> Test();
  <font color=#0000ff>private</font> <font color=#0000ff>int</font> i;
  <font color=#0000ff>public</font> 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);
    monitor.expect(<font color=#0000ff>new</font> String[] {
      <font color=#004488>"x: 7"</font>,
      <font color=#004488>"y: 7"</font>,
      <font color=#004488>"Incrementing x"</font>,
      <font color=#004488>"x: 8"</font>,
      <font color=#004488>"y: 8"</font>
    });
  }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE><p><br></p>
<p>In the line:<br></p>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE>Alias1 y = x; <font color=#009900>// Assign the reference</font></PRE></FONT></BLOCKQUOTE><p><br></p>
<p>a new <b>Alias1</b> reference is created, but instead of being assigned to a fresh object created with <b>new</b>, it&#146;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>&#146;s <b>i</b> is incremented in the statement: <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]AppendA_2703" title="Send BackTalk Comment">Feedback</a></font><br></p>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE>x.i++;</PRE></FONT></BLOCKQUOTE><p><br></p>
<p><b>y</b>&#146;s <b>i </b>will be affected as well. This can be seen in the output:<br></p>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE>x: 7
y: 7
Incrementing x
x: 8
y: 8</PRE></FONT></BLOCKQUOTE><p><br></p>
<p>One good solution in this case is simply not to do it; don&#146;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&#146;re passing a reference in as an argument&#151;which is the way Java is supposed to work&#151;you automatically alias, because the local reference that&#146;s created can modify the &#147;outside object&#148; (the object that was created outside the scope of the method). Here&#146;s an example: <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]AppendA_2704" title="Send BackTalk Comment">Feedback</a></font><br></p>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: appendixa:Alias2.java</font>
<font color=#009900>// Method calls implicitly alias their arguments.</font>
<font color=#0000ff>import</font> com.bruceeckel.simpletest.*;

<font color=#0000ff>public</font> <font color=#0000ff>class</font> Alias2 {
  <font color=#0000ff>private</font> <font color=#0000ff>static</font> Test monitor = <font color=#0000ff>new</font> Test();
  <font color=#0000ff>private</font> <font color=#0000ff>int</font> i;
  <font color=#0000ff>public</font> Alias2(<font color=#0000ff>int</font> ii) { i = ii; }
  <font color=#0000ff>public</font> <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);
    monitor.expect(<font color=#0000ff>new</font> String[] {
      <font color=#004488>"x: 7"</font>,
      <font color=#004488>"Calling f(x)"</font>,
      <font color=#004488>"x: 8"</font>
    });
  }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE><p><br></p>
<p>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&#146;s going to cause problems. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]AppendA_2705" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>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>. It&#146;s much less common to call a method in order to manipulate its arguments; this is referred to as &#147;calling a method for its <a name="Index2152"></a><i>side effects</i>.&#148; Thus, when you create a 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&#146;s much better to avoid changing the argument. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]AppendA_2706" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>If you need to modify an argument during a method call and you don&#146;t intend to modify the outside argument, then you should protect that argument by making a copy inside your method. That&#146;s the subject of much of this appendix. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]AppendA_2707" title="Send BackTalk Comment">Feedback</a></font><br></p>
<h2>
<a name="_Toc24775991"></a><a name="Heading24585"></a>Making local copies</h2>
<p>To review: All argument passing in Java is performed by passing references. That is, when you pass &#147;an object,&#148; you&#146;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 size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]A0098" title="Send BackTalk Comment">Feedback</a></font><br></p>
<ul>
<li>Aliasing happens automatically during argument passing.</li>
<li>There are no local objects, only local references.</li>
<li>References have scopes, objects do not.</li>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -