📄 tij0081.html
字号:
}
<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">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
class
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>TrackingSlip</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is nested inside the scope of an
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>if</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
statement. This does not mean that the class is conditionally created –
it gets compiled along with everything else. However, it’s not available
outside the scope in which it is defined.
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Other
than that, it looks just like an ordinary class.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
next example looks a little strange:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: Parcel6.java</font>
<font color="#009900">// A method that returns an anonymous inner class</font>
<font color="#0000ff">package</font> c07.innerscopes;
<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">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>cont( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
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
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Contents</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object:
</FONT><P></DIV><DIV ALIGN=LEFT><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">return
new Contents()
</FONT></TT><P></DIV><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">but
then, before you get to the semicolon, you say, “But wait, I think
I’ll slip in a class definition”:
</FONT><P></DIV>
<font color="#990000"><PRE><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; }
};</PRE></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">What
this strange syntax means is “create an object of an anonymous class
that’s inherited from
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Contents</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.”
The handle returned by the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>new</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
expression is automatically upcast to a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Contents</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
handle. The anonymous inner class syntax is a shorthand for:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#0000ff">class</font> MyContents <font color="#0000ff">extends</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">return</font> <font color="#0000ff">new</font> MyContents(); </PRE></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">In
the anonymous inner class,
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Contents</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is created using a default constructor. The following code shows what to do if
your base class needs a constructor with an argument:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: Parcel7.java</font>
<font color="#009900">// An anonymous inner class that calls the </font>
<font color="#009900">// base-class constructor</font>
<font color="#0000ff">package</font> c07.innerscopes;
<font color="#0000ff">public</font> <font color="#0000ff">class</font> Parcel7 {
<font color="#0000ff">public</font> Wrapping wrap(<font color="#0000ff">int</font> x) {
<font color="#009900">// Base constructor call:</font>
<font color="#0000ff">return</font> <font color="#0000ff">new</font> Wrapping(x) {
<font color="#0000ff">public</font> <font color="#0000ff">int</font> value() {
<font color="#0000ff">return</font> <font color="#0000ff">super</font>.value() * 47;
}
}; <font color="#009900">// Semicolon required</font>
}
<font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
Parcel7 p = <font color="#0000ff">new</font> Parcel7();
Wrapping w = p.wrap(10);
}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">That
is, you simply pass the appropriate argument to the base-class constructor,
seen here as the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>x
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">passed
in
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>new
Wrapping(x)
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
An anonymous class cannot have a constructor where you would normally call
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>super( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">In
both of the previous examples, the semicolon doesn’t mark the end of the
class body (as it does in C++). Instead, it marks the end of the expression
that happens to contain the anonymous class. Thus, it’s identical to the
use of the semicolon everywhere else.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">What
happens if you need to perform some kind of initialization for an object of an <A NAME="Index631"></A><A NAME="Index632"></A><A NAME="Index633"></A>anonymous
inner class? Since it’s anonymous, there’s no name to give the
constructor so you can’t have a constructor. You can, however, perform
initialization at the point of definition of your fields:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: Parcel8.java</font>
<font color="#009900">// An anonymous inner class that performs </font>
<font color="#009900">// initialization. A briefer version</font>
<font color="#009900">// of Parcel5.java.</font>
<font color="#0000ff">package</font> c07.innerscopes;
<font color="#0000ff">public</font> <font color="#0000ff">class</font> Parcel8 {
<font color="#009900">// Argument must be final to use inside </font>
<font color="#009900">// anonymous inner class:</font>
<font color="#0000ff">public</font> Destination dest(<font color="#0000ff">final</font> String dest) {
<font color="#0000ff">return</font> <font color="#0000ff">new</font> Destination() {
<font color="#0000ff">private</font> String label = dest;
<font color="#0000ff">public</font> String readLabel() { <font color="#0000ff">return</font> label; }
};
}
<font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
Parcel8 p = <font color="#0000ff">new</font> Parcel8();
Destination d = p.dest("Tanzania");
}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">If
you’re defining an anonymous inner class and want to use an object
that’s defined outside the anonymous inner class, the compiler requires
that the outside object be
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>final</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
This is why the argument to
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>dest( )
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">is
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>final</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">If
you forget, you’ll get a compile-time error message.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">As
long as you’re simply assigning a field, the above approach is fine. But
what if you need to perform some constructor-like activity? With Java 1.1<A NAME="Index634"></A>
<A NAME="Index635"></A><A NAME="Index636"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>instance
initialization
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
you can, in effect, create a constructor for an anonymous inner class:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: Parcel9.java</font>
<font color="#009900">// Using "instance initialization" to perform </font>
<font color="#009900">// construction on an anonymous inner class</font>
<font color="#0000ff">package</font> c07.innerscopes;
<font color="#0000ff">public</font> <font color="#0000ff">class</font> Parcel9 {
<font color="#0000ff">public</font> Destination
dest(<font color="#0000ff">final</font> String dest, <font color="#0000ff">final</font> <font color="#0000ff">float</font> price) {
<font color="#0000ff">return</font> <font color="#0000ff">new</font> Destination() {
<font color="#0000ff">private</font> <font color="#0000ff">int</font> cost;
<font color="#009900">// Instance initialization for each object:</font>
{
cost = Math.round(price);
<font color="#0000ff">if</font>(cost > 100)
System.out.println("Over budget!");
}
<font color="#0000ff">private</font> String label = dest;
<font color="#0000ff">public</font> String readLabel() { <font color="#0000ff">return</font> label; }
};
}
<font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
Parcel9 p = <font color="#0000ff">new</font> Parcel9();
Destination d = p.dest("Tanzania", 101.395F);
}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Inside
the instance initializer you can see code that couldn’t be executed as
part of a field initializer (that is, the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>if</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
statement). So in effect, an instance initializer is the constructor for an
anonymous inner class. Of course, it’s limited; you can’t overload
instance initializers so you can have only one of these constructors.
</FONT><a name="_Toc408018546"></a><P></DIV>
<A NAME="Heading224"></A><H3 ALIGN=LEFT>
The
link to the outer class
</H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">So
far, it appears that inner classes are just a name-hiding and code-organization
scheme, which is helpful but not totally compelling. However, there’s
another twist. When you create an inner class, objects of that inner class have
a link to the enclosing object that made them, and so they can access the
members of that enclosing object –
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>without
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">any
special qualifications. In addition, <A NAME="Index637"></A><A NAME="Index638"></A><A NAME="Index639"></A>inner
classes have access rights to all the elements in the enclosing class.
</FONT><A NAME="fnB29" HREF="#fn29">[29]</A><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
The following example demonstrates this:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: Sequence.java</font>
<font color="#009900">// Holds a sequence of Objects</font>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -