📄 tij310.htm
字号:
<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>public</font> <font color=#0000ff>class</font> TestParcel {
<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><p><br></p>
<p>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>. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap08_1146" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>In <b>Parcel3</b>, something new has been added: The inner class <b>PContents</b> is <b>private</b>,<b> </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 same package (since <b>protected</b> also gives package access), 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 TestParcel</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>. This also provides an opportunity for the Java compiler to generate more efficient code. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap08_1147" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>Normal (non-inner) classes cannot be made <b>private</b> or <b>protected</b>; they may only be given <b>public</b> or package access. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap08_1148" title="Send BackTalk Comment">Feedback</a></font><br></p>
<h3>
<a name="_Toc24775682"></a><a name="Heading7358"></a>Inner classes <br>in
methods and scopes<br></h3>
<p><a name="Index723"></a><a name="Index724"></a><a name="Index725"></a><a name="Index726"></a>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: <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap08_1149" title="Send BackTalk Comment">Feedback</a></font><br></p>
<ol>
<li>As shown previously, you’re implementing an interface of some kind so
that you can create and return a reference. <font size="-2"><a
href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap08_1150" title="Send BackTalk
Comment">Feedback</a></font></li>
<li>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. <font
size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap08_1151"
title="Send BackTalk
Comment">Feedback</a></font></li></ol><p>In the following examples, the previous code will be modified to use: <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap08_1152" title="Send BackTalk Comment">Feedback</a></font><br></p>
<ol>
<li><a name="Index727"></a><a name="Index728"></a><a name="Index729"></a>A class
defined within a method </li>
<li>A class defined within a scope inside a method</li>
<li>An anonymous class implementing an interface</li>
<li>An anonymous class extending a class that has a nondefault constructor</li>
<li>An anonymous class that performs field initialization</li>
<li>An anonymous class that performs construction using instance initialization
(anonymous inner classes cannot have
constructors)</li></ol><p>Although it’s an ordinary class with an implementation, <b>Wrapping</b> is also being used as a common “interface” to its derived classes:<br></p>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c08:Wrapping.java</font>
<font color=#0000ff>public</font> <font color=#0000ff>class</font> Wrapping {
<font color=#0000ff>private</font> <font color=#0000ff>int</font> i;
<font color=#0000ff>public</font> Wrapping(<font color=#0000ff>int</font> x) { i = x; }
<font color=#0000ff>public</font> <font color=#0000ff>int</font> value() { <font color=#0000ff>return</font> i; }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE><p><br></p>
<p>You’ll notice that <b>Wrapping</b> has a constructor that requires an argument, to make things a bit more interesting. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap08_1153" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>The first example shows the creation of an entire class within the scope of a method (instead of the scope of another class). This is called a <i>local inner class</i>:<br></p>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c08:Parcel4.java</font>
<font color=#009900>// Nesting a class within a method.</font>
<font color=#0000ff>public</font> <font color=#0000ff>class</font> Parcel4 {
<font color=#0000ff>public</font> Destination dest(String s) {
<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>return</font> <font color=#0000ff>new</font> PDestination(s);
}
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
Parcel4 p = <font color=#0000ff>new</font> Parcel4();
Destination d = p.dest(<font color=#004488>"Tanzania"</font>);
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE><p><br></p>
<p>The class <b>PDestination</b> is part of <b>dest( )</b> rather than being part of <b>Parcel4</b>. (Also notice that you could use the class identifier <b>PDestination </b>for an inner class inside each class in the same subdirectory without a name clash.) Therefore, <b>PDestination </b>cannot be accessed outside of <b>dest( )</b>.<b> </b>Notice the upcasting that occurs in the return statement—nothing comes out of <b>dest( )</b> except a reference to <b>Destination</b>, the base class. Of course, the fact that the name of the class <b>PDestination</b> is placed inside <b>dest( )</b> doesn’t mean that <b>PDestination</b> is not a valid object once <b>dest( )</b> returns. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap08_1154" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>The next example shows how you can nest an inner class within any arbitrary scope:<br></p>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c08:Parcel5.java</font>
<font color=#009900>// Nesting a class within a scope.</font>
<font color=#0000ff>public</font> <font color=#0000ff>class</font> Parcel5 {
<font color=#0000ff>private</font> <font color=#0000ff>void</font> internalTracking(<font color=#0000ff>boolean</font> b) {
<font color=#0000ff>if</font>(b) {
<font color=#0000ff>class</font> TrackingSlip {
<font color=#0000ff>private</font> String id;
TrackingSlip(String s) {
id = s;
}
String getSlip() { <font color=#0000ff>return</font> id; }
}
TrackingSlip ts = <font color=#0000ff>new</font> TrackingSlip(<font color=#004488>"slip"</font>);
String s = ts.getSlip();
}
<font color=#009900>// Can't use it here! Out of scope:</font>
<font color=#009900>//! TrackingSlip ts = new TrackingSlip("x");</font>
}
<font color=#0000ff>public</font> <font color=#0000ff>void</font> track() { internalTracking(<font color=#0000ff>true</font>); }
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
Parcel5 p = <font color=#0000ff>new</font> Parcel5();
p.track();
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE><p><br></p>
<p>The class <b>TrackingSlip</b> is nested inside the scope of an <b>if</b> statement. This does not mean that the <i>class</i> is conditionally created—it gets compiled along with everything else. However, it’s not available outside the scope in which it is defined.<b> </b>Other than that, it looks just like an ordinary class. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap08_1155" title="Send BackTalk Comment">Feedback</a></font><br></p>
<h3>
<a name="_Toc24775683"></a><a name="Heading7428"></a>Anonymous inner
classes</h3>
<p>The next example looks a little strange:<br></p>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c08:Parcel6.java</font>
<font color=#009900>// A method that returns an anonymous inner class.</font>
<font color=#0000ff>public</font> <font color=#0000ff>class</font> Parcel6 {
<font color=#0000ff>public</font> Contents cont() {
<font color=#0000ff>return</font> <font color=#0000ff>new</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=#009900>// Semicolon required in this case</font>
}
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
Parcel6 p = <font color=#0000ff>new</font> Parcel6();
Contents c = p.cont();
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE><p><br></p>
<p>The <b>cont( )</b> method combines the creation of the return value with the definition of the class that represents that return value! In addition, the class is anonymous; it has no name. To make matters a bit worse, it looks like you’re starting out to create a <b>Contents</b> object: <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap08_1156" title="Send BackTalk Comment">Feedback</a></font><br></p>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#0000ff>return</font> <font color=#0000ff>new</font> Contents()</PRE></FONT></BLOCKQUOTE><p><br></p>
<p>But then, before you get to the semicolon, you say, “But wait, I think I’ll slip in a class definition”: <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap08_1157" title="Send BackTalk Comment">Feedback</a></font><br></p>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#0000ff>return</font> <font color=#0000ff>new</font> Contents() {
<font color=#0000ff>private</font> <font col
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -