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

📄 tij0081.html

📁 学习java的经典书籍
💻 HTML
📖 第 1 页 / 共 5 页
字号:
    }
    <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 &#8211;
it gets compiled along with everything else. However, it&#8217;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(&#160;)</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
&#8211; it has no name. To make matters a bit worse, it looks like you&#8217;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, &#8220;But wait, I think
I&#8217;ll slip in a class definition&#8221;:
</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 &#8220;create an object of an anonymous class
that&#8217;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">.&#8221;
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(&#160;)</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&#8217;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&#8217;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&#8217;s anonymous, there&#8217;s no name to give the
constructor so you can&#8217;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&#8217;re defining an anonymous inner class and want to use an object
that&#8217;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(&#160;)
</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&#8217;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&#8217;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 &gt; 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&#8217;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&#8217;s limited; you can&#8217;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&#8217;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 &#8211; 
</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 + -