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

📄 chap08.htm

📁 Thinking in Java, 2nd edition
💻 HTM
📖 第 1 页 / 共 5 页
字号:
    p.ship(<font color=#004488>"Tanzania"</font>);
  }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The inner classes, when used inside
<B>ship(&#160;)</B>, look just like the use of any other classes. Here, the only
practical difference is that the names are nested within <B>Parcel1</B>.
You&#8217;ll see in a while that this isn&#8217;t the only difference.

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER8_I33' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER8_I34>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">More typically, an outer class will have
a method that returns a reference to an inner class, like this:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c08:Parcel2.java</font>
<font color=#009900>// Returning a reference to an inner class.</font>

<font color=#0000ff>public</font> <font color=#0000ff>class</font> Parcel2 {
  <font color=#0000ff>class</font> Contents {
    <font color=#0000ff>private</font> <font color=#0000ff>int</font> i = 11;
    <font color=#0000ff>public</font> <font color=#0000ff>int</font> value() { <font color=#0000ff>return</font> i; }
  }
  <font color=#0000ff>class</font> Destination {
    <font color=#0000ff>private</font> String label;
    Destination(String whereTo) {
      label = whereTo;
    }
    String readLabel() { <font color=#0000ff>return</font> label; }
  }
  <font color=#0000ff>public</font> Destination to(String s) {
    <font color=#0000ff>return</font> <font color=#0000ff>new</font> Destination(s);
  }
  <font color=#0000ff>public</font> Contents cont() { 
    <font color=#0000ff>return</font> <font color=#0000ff>new</font> Contents(); 
  }
  <font color=#0000ff>public</font> <font color=#0000ff>void</font> ship(String dest) {
    Contents c = cont();
    Destination d = to(dest);
    System.out.println(d.readLabel());
  }  
  <font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
    Parcel2 p = <font color=#0000ff>new</font> Parcel2();
    p.ship(<font color=#004488>"Tanzania"</font>);
    Parcel2 q = <font color=#0000ff>new</font> Parcel2();
    <font color=#009900>// Defining references to inner classes:</font>
    Parcel2.Contents c = q.cont();
    Parcel2.Destination d = q.to(<font color=#004488>"Borneo"</font>);
  }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">If you want to make an object of the
inner class anywhere except from within a non-<B>static</B> method of the outer
class, you must specify the type of that object as
<I>OuterClassName.InnerClassName</I>, as seen in <B>main(&#160;)</B>.

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER8_I34' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER8_I35>
</FONT><A NAME="_Toc481064650"></A><BR></P></DIV>
<A NAME="Heading261"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Inner classes and
upcasting<BR><A NAME="Index783"></A><A NAME="Index784"></A><A NAME="Index785"></A></H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">So far, inner classes don&#8217;t seem
that dramatic. After all, if it&#8217;s hiding you&#8217;re after, Java already
has a perfectly good hiding mechanism&#8212;just allow the class to be
&#8220;<A NAME="Index786"></A>friendly&#8221; (visible only within a
<A NAME="Index787"></A><A NAME="Index788"></A>package) rather than creating it
as an inner class. 
</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER8_I35' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER8_I36>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><A NAME="Index789"></A><FONT FACE="Georgia">However, inner
classes really come into their own when you start upcasting to a base class, and
in particular to an <B>interface</B>. (The effect of producing an interface
reference from an object that implements it is essentially the same as upcasting
to a base class.) That&#8217;s because the inner class&#8212;the implementation
of the <B>interface</B>&#8212;can then be completely unseen and unavailable to
anyone, which is convenient for hiding the implementation. All you get back is a
reference to the base class or the <B>interface</B>. 

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER8_I36' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER8_I37>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">First, the common interfaces will be
defined in their own files so they can be used in all the
examples:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c08:Destination.java</font>
<font color=#0000ff>public</font> <font color=#0000ff>interface</font> Destination {
  String readLabel();
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c08:Contents.java</font>
<font color=#0000ff>public</font> <font color=#0000ff>interface</font> Contents {
  <font color=#0000ff>int</font> value();
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Now <B>Contents</B> and
<B>Destination</B> represent interfaces available to the client programmer. (The
<B>interface</B>, remember, automatically makes all of its members
<B>public</B>.)  
</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER8_I37' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER8_I38>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">When you get back a reference to the base
class or the <B>interface</B>, it&#8217;s possible that you can&#8217;t even
find out the exact type, as shown here:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c08:Parcel3.java</font>
<font color=#009900>// Returning a reference to an inner class.</font>

<font color=#0000ff>public</font> <font color=#0000ff>class</font> Parcel3 {
  <font color=#0000ff>private</font> <font color=#0000ff>class</font> PContents <font color=#0000ff>implements</font> Contents {
    <font color=#0000ff>private</font> <font color=#0000ff>int</font> i = 11;
    <font color=#0000ff>public</font> <font color=#0000ff>int</font> value() { <font color=#0000ff>return</font> i; }
  }
  <font color=#0000ff>protected</font> <font color=#0000ff>class</font> PDestination
      <font color=#0000ff>implements</font> Destination {
    <font color=#0000ff>private</font> String label;
    <font color=#0000ff>private</font> PDestination(String whereTo) {
      label = whereTo;
    }
    <font color=#0000ff>public</font> String readLabel() { <font color=#0000ff>return</font> label; }
  }
  <font color=#0000ff>public</font> Destination dest(String s) {
    <font color=#0000ff>return</font> <font color=#0000ff>new</font> PDestination(s);
  }
  <font color=#0000ff>public</font> Contents cont() { 
    <font color=#0000ff>return</font> <font color=#0000ff>new</font> PContents(); 
  }
}

<font color=#0000ff>class</font> Test {
  <font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
    Parcel3 p = <font color=#0000ff>new</font> Parcel3();
    Contents c = p.cont();
    Destination d = p.dest(<font color=#004488>"Tanzania"</font>);
    <font color=#009900>// Illegal -- can't access private class:</font>
    <font color=#009900>//! Parcel3.PContents pc = p.new PContents();</font>
  }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Note that since <B>main(&#160;) </B>is in
<B>Test</B>, when you want to run this program you don&#8217;t execute
<B>Parcel3</B>, but instead:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE>java Test</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In the example, <B>main(&#160;) </B>must
be in a separate class in order to demonstrate the privateness of the inner
class <B>PContents</B>. 
</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER8_I38' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER8_I39>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In <B>Parcel3</B>, something new has been
added: the inner class <B>PContents</B> is <B>private </B>so no one but
<B>Parcel3</B> can access it. <B>PDestination</B> is <B>protected</B>, so no one
but <B>Parcel3</B>, classes in the <B>Parcel3</B> package (since
<B>protected</B> also gives package access&#8212;that is, <B>protected</B> is
also &#8220;friendly&#8221;), and the inheritors of <B>Parcel3 </B>can access
<B>PDestination</B>. This means that the client programmer has restricted
knowledge and access to these members. In fact, you can&#8217;t even downcast to
a <B>private</B> inner class (or a <B>protected</B> inner class unless
you&#8217;re an inheritor), because you can&#8217;t access the name, as you can
see in <B>class Test</B>. Thus, the <B>private</B> inner class provides a way
for the class designer to completely prevent any type-coding dependencies and to
completely hide details about implementation. In addition, extension of an
<B>interface</B> is useless from the client programmer&#8217;s perspective since
the client programmer cannot access any additional methods that aren&#8217;t
part of the <B>public</B> <B>interface</B><STRIKE> class</STRIKE>. This also
provides an opportunity for the Java compiler to generate more efficient code.

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER8_I39' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER8_I40>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Normal (non-inner) classes cannot be made
<B>private</B> or <B>protected&#8212;</B>only <B>public</B> or
&#8220;friendly.&#8221;

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER8_I40' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER8_I41>
</FONT><A NAME="_Toc481064651"></A><BR></P></DIV>
<A NAME="Heading262"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Inner classes <BR>in methods and
scopes<BR><A NAME="Index790"></A><A NAME="Index791"></A><A NAME="Index792"></A><A NAME="Index793"></A></H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">What you&#8217;ve seen so far encompasses
the typical use for inner classes. In general, the code that you&#8217;ll write
and read involving inner classes will be &#8220;plain&#8221; inner classes that
are simple and easy to understand. However, the design for inner classes is
quite complete and there are a number of other, more obscure, ways that you can
use them if you choose: inner classes can be created within a method or even an
arbitrary scope. There are two reasons for doing this:

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER8_I41' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER8_I42>
</FONT><BR></P></DIV>
<OL>
<LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">As shown previously,
you&#8217;re implementing an interface of some kind so that you can create and
return a reference.

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER8_I42' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER8_I43>
</FONT><LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">You&#8217;re
solving a complicated problem and you want to create a class to aid in your
solution, but you don&#8217;t want it publicly available.

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER8_I43' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER8_I44>
</FONT></OL><DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In
the following examples, the previous code will be modified to use:
<A NAME="Index794"></A><A NAME="Index795"></A><A NAME="Index796"></A>

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER8_I44' 
  target="_blank">Add&nbsp;C

⌨️ 快捷键说明

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