📄 chap08.htm
字号:
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( )</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’ll see in a while that this isn’t the only difference.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER8_I33'
target="_blank">Add Comment</a> ]
<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( )</B>.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER8_I34'
target="_blank">Add Comment</a> ]
<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’t seem
that dramatic. After all, if it’s hiding you’re after, Java already
has a perfectly good hiding mechanism—just allow the class to be
“<A NAME="Index786"></A>friendly” (visible only within a
<A NAME="Index787"></A><A NAME="Index788"></A>package) rather than creating it
as an inner class.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER8_I35'
target="_blank">Add Comment</a> ]
<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’s because the inner class—the implementation
of the <B>interface</B>—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>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER8_I36'
target="_blank">Add Comment</a> ]
<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>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER8_I37'
target="_blank">Add Comment</a> ]
<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’s possible that you can’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( ) </B>is in
<B>Test</B>, when you want to run this program you don’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( ) </B>must
be in a separate class in order to demonstrate the privateness of the inner
class <B>PContents</B>.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER8_I38'
target="_blank">Add Comment</a> ]
<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—that is, <B>protected</B> is
also “friendly”), 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’t even downcast to
a <B>private</B> inner class (or a <B>protected</B> inner class unless
you’re an inheritor), because you can’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’s perspective since
the client programmer cannot access any additional methods that aren’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>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER8_I39'
target="_blank">Add Comment</a> ]
<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—</B>only <B>public</B> or
“friendly.”
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER8_I40'
target="_blank">Add Comment</a> ]
<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’ve seen so far encompasses
the typical use for inner classes. In general, the code that you’ll write
and read involving inner classes will be “plain” 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>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER8_I41'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER8_I42>
</FONT><BR></P></DIV>
<OL>
<LI><FONT FACE="Verdana"> </FONT><FONT FACE="Georgia">As shown previously,
you’re implementing an interface of some kind so that you can create and
return a reference.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER8_I42'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER8_I43>
</FONT><LI><FONT FACE="Verdana"> </FONT><FONT FACE="Georgia">You’re
solving a complicated problem and you want to create a class to aid in your
solution, but you don’t want it publicly available.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER8_I43'
target="_blank">Add Comment</a> ]
<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>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER8_I44'
target="_blank">Add C
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -