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

📄 tij0081.html

📁 学习java的经典书籍
💻 HTML
📖 第 1 页 / 共 5 页
字号:
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interface</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
but a 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>static</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
inner class can be part of an 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interface</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
Since the class is 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>static
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">it
doesn't violate the rules for interfaces &#8211; the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>static
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">inner
class is only placed inside the namespace of the interface:
</FONT><P></DIV>

<font color="#990000"><PRE><font color="#009900">//: IInterface.java</font>
<font color="#009900">// Static inner classes inside interfaces</font>

<font color="#0000ff">class</font> IInterface {
  <font color="#0000ff">static</font> <font color="#0000ff">class</font> Inner {
    <font color="#0000ff">int</font> i, j, k;
    <font color="#0000ff">public</font> Inner() {}
    <font color="#0000ff">void</font> f() {}
  }
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Earlier
in the book I suggested putting a 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>main(&#160;)
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">in
every class to act as a test<A NAME="Index646"></A>
bed for that class. One drawback to this is the amount of extra code you must
carry around. If this is a problem, you can use a 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>static</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
inner class to hold your test code:
</FONT><P></DIV>

<font color="#990000"><PRE><font color="#009900">//: TestBed.java</font>
<font color="#009900">// Putting test code in a static inner class</font>

<font color="#0000ff">class</font> TestBed {
  TestBed() {}
  <font color="#0000ff">void</font> f() { System.out.println("f()"); }
  <font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">class</font> Tester {
    <font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
      TestBed t = <font color="#0000ff">new</font> TestBed();
      t.f();
    }
  }
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">This
generates a separate class called 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>TestBed$Tester</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
(to run the program you say 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>java
TestBed$Tester
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">).
You can use this class for testing, but you don't need to include it in your
shipping product.
</FONT><a name="_Toc408018548"></a><P></DIV>
<A NAME="Heading226"></A><H3 ALIGN=LEFT>
Referring
to the outer class object
<P><A NAME="Index647"></A><A NAME="Index648"></A></H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">If
you need to produce the handle to the outer class object, you name the outer
class followed by a dot and 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>this</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
For example, in the class 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Sequence.SSelector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
any of its methods can produce the stored handle to the outer class 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Sequence</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
by saying 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Sequence.this</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
The resulting handle is automatically the correct type. (This is known and
checked at compile time, so there is no run-time overhead.)
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Sometimes
you want to tell some other object to create an object of one of its inner
classes. To do this you must provide a handle to the other outer class object
in 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, like this:
</FONT><P></DIV>

<font color="#990000"><PRE><font color="#009900">//: Parcel11.java</font>
<font color="#009900">// Creating inner classes</font>
<font color="#0000ff">package</font> c07.parcel11;

<font color="#0000ff">public</font> <font color="#0000ff">class</font> Parcel11 {
  <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> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
    Parcel11 p = <font color="#0000ff">new</font> Parcel11();
    <font color="#009900">// Must use instance of outer class</font>
    <font color="#009900">// to create an instances of the inner class:</font>
    Parcel11.Contents c = p.<font color="#0000ff">new</font> Contents();
    Parcel11.Destination d =
      p.<font color="#0000ff">new</font> Destination("Tanzania");
  }
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">To
create an object of the inner class directly, you don&#8217;t follow the same
form and refer to the outer class name 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Parcel11</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
as you might expect, but instead you must use an 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>object</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
of the outer class to make an object of the inner class:
</FONT><P></DIV><DIV ALIGN=LEFT><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">Parcel11.Contents
c = p.new Contents();
</FONT></TT><P></DIV><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Thus,
it&#8217;s not possible to create an object of the inner class unless you
already have an object of the outer class. This is because the object of the
inner class is quietly connected to the object of the outer class that it was
made from. However, if you make a 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>static</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
inner class, then it doesn&#8217;t need a handle to the outer class object.
</FONT><a name="_Toc408018549"></a><P></DIV>
<A NAME="Heading227"></A><H3 ALIGN=LEFT>
Inheriting
from inner classes
<P><A NAME="Index649"></A><A NAME="Index650"></A><A NAME="Index651"></A></H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Because
the inner class constructor must attach to a handle of the enclosing class
object, things are slightly complicated when you inherit from an inner class.
The problem is that the &#8220;secret&#8221; handle to the enclosing class
object 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>must</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
be initialized, and yet in the derived class there&#8217;s no longer a default
object to attach to. The answer is to use a syntax provided to make the
association explicit:
</FONT><P></DIV>

<font color="#990000"><PRE><font color="#009900">//: InheritInner.java</font>
<font color="#009900">// Inheriting an inner class</font>

<font color="#0000ff">class</font> WithInner {
  <font color="#0000ff">class</font> Inner {}
}

<font color="#0000ff">public</font> <font color="#0000ff">class</font> InheritInner 
    <font color="#0000ff">extends</font> WithInner.Inner {
  <font color="#009900">//! InheritInner() {} // Won't compile</font>
  InheritInner(WithInner wi) {
    wi.<font color="#0000ff">super</font>();
  }
  <font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
    WithInner wi = <font color="#0000ff">new</font> WithInner();
    InheritInner ii = <font color="#0000ff">new</font> InheritInner(wi);
  }
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">You
can see that 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>InheritInner</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is extending only the inner class, not the outer one. But when it comes time to
create a constructor, the default one is no good and you can&#8217;t just pass
a handle to an enclosing object. In addition, you must use the syntax
</FONT><P></DIV><DIV ALIGN=LEFT><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">enclosingClassHandle.super();</FONT></TT><P></DIV><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><A NAME="Index652"></A><A NAME="Index653"></A><A NAME="Index654"></A><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">inside
the constructor. This provides the necessary handle and the program will then
compile.
</FONT><a name="_Toc408018550"></a><P></DIV>
<A NAME="Heading228"></A><H3 ALIGN=LEFT>
Can
inner classes be overridden?
</H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">What
happens when you create an inner class, then inherit from the enclosing class
and redefine the inner class? That is, is it possible to override an inner
class? This seems like it would be a powerful concept, but <A NAME="Index655"></A><A NAME="Index656"></A><A NAME="Index657"></A>&#8220;overriding&#8221;
an inner class as if it were another method of the outer class doesn&#8217;t
really do anything:
</FONT><P></DIV>

<font color="#990000"><PRE><font color="#009900">//: BigEgg.java</font>
<font color="#009900">// An inner class cannot be overriden </font>
<font color="#009900">// like a method</font>

<font color="#0000ff">class</font> Egg {
  <font color="#0000ff">protected</font> <font color="#0000ff">class</font> Yolk {
    <font color="#0000ff">public</font> Yolk() {
      System.out.println("Egg.Yolk()");
    }
  }
  <font color="#0000ff">private</font> Yolk y;
  <font color="#0000ff">public</font> Egg() {
    System.out.println("New Egg()");
    y = <font color="#0000ff">new</font> Yolk();
  }
}

<font color="#0000ff">public</font> <font color="#0000ff">class</font> BigEgg <font color="#0000ff">extends</font> Egg {
  <font color="#0000ff">public</font> <font color="#0000ff">class</font> Yolk {
    <font color="#0000ff">public</font> Yolk() {
      System.out.println("BigEgg.Yolk()");
    }
  }
  <font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
    <font color="#0000ff">new</font> BigEgg();
  }
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
default constructor is synthesized automatically by the compiler, and this
calls the base-class default constructor. You might think that since a 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>BigEgg</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is being created, the &#8220;overridden&#8221; version of 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Yol

⌨️ 快捷键说明

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