Java内部类

[来源] 达内    [编辑] 达内   [时间]2012-11-01

创建内部类的时候只需要将内部类放到外部类的打括号内部就可以,如果需要实例化这个内部类,只要不是在外部类的非静态方法中,必须使用外部类名称加上内部类名称来表示这个类

创建内部类

  创建内部类的时候只需要将内部类放到外部类的打括号内部就可以,如果需要实例化这个内部类,只要不是在外部类的非静态方法中,必须使用外部类名称加上内部类名称来表示这个类:

//
: innerclasses/ // Returning a reference to an inner class.

public class
 Parcel2 {   class
 Contents {     private
 int i = 11;     
public int
 value() { return
 i; }   }   

class Destination {     private
 String label;     Destination(String whereTo) {       label = whereTo;     }     String readLabel() { 
return label; }   }   
public
 Destination to(String s) {     

return new
 Destination(s);   }   
public

 Contents contents() {     
return

 new Contents();   }   
public void
 ship(String dest) {     Contents c 
= contents();     Destination d 

= to(dest);     System.out.println(d.readLabel());   }   
public

 static void
 main(String[] args) {     Parcel2 p 
= new

 Parcel2();     p.ship(
"Tasmania"

);     Parcel2 q = new
 Parcel2();     //
 Defining references to inner classes:

    Parcel2.Contents c = q.contents();     Parcel2.Destination d 
= ("Borneo");   } } 
/*

 Output: Tasmania *///
:~

与外部类的连接

  看起来内部类只是一种命名隐藏和代码组织的方式,并不是强制性的语法 但是,这里有另外一点需要注意。当你创建一个内部类的时候,这个内部类的对象具有对与创建这个内部类的对象的连接,它可以获取到创建它的类的对象中的成员,而不用其他特殊的标识。另外,内部类具有对外部类所有成员的访问权限,如下面的代码:

//
: innerclasses/ 
//

 Holds a sequence of Objects.

interface Selector {   
boolean
 end();   Object current();   void
 next(); } 

public class
 Sequence {   private
 Object[] items;   private
 int next = 0;   
public Sequence(int
 size) { items = new
 Object[size]; }   

public void
 add(Object x) {     if
(next < items.length)       items[next
++] = x;   }   

private class
 SequenceSelector implements
 Selector {     

private int
 i = 0;     public
 boolean end() { return
 i == items.length; }     
public

 Object current() { return
 items[i]; }     

public void
 next() { if(i < items.length) i++
; }   }   

public
 Selector selector() {     

return new
 SequenceSelector();   }   
public

 static void
 main(String[] args) {     Sequence sequence 
= new

 Sequence(10);     for
(int i = 0; i < 10; i++
)       sequence.add(Integer.toString(i));     Selector selector = sequence.selector();     
while(!
selector.end()) {       System.out.print(selector.current() 

+ " ");       ();     }   } } 
/*
 Output: 0 1 2 3 4 5 6 7 8 9 

*///:~

  从上面的代码中我们可以看到内部类具有对外部类的所有成员的访问权限。内部类创建的时候必须与对应的外部类相关联,使得内部类能够抓取创建它的外部类的实例。

使用this和new

  用外部类的名字跟上.this表示外部类对象的引用,如下:

//
: innerclasses/ // Qualifying access to the outer-class object.

public class
 DotThis {   void
 f() { System.out.println("DotThis.f()"); }   


public class
 Inner {     

public
 DotThis outer() {       return
 DotThis.this

;       //
 A plain "this" would be Inner’s "this"

    }   }   
public Inner inner() { return new Inner(); }   public
 static void
 main(String[] args) {     DotThis dt 
= new

 DotThis();     DotThis.Inner dti 
=

 dt.inner();     dti.outer().f();   } } /*
 Output: DotThis.f() *///
:~

  当你已经获得了某个外部类的实例的引用,当你需要创建这个外部类实例的一个内部类实例的时候,关键字,如下:

//
: innerclasses/ // Using .new to create instances of inner classes.

public class
 Parcel3 {   class
 Contents {     private
 int i = 11;     
public int
 value() { return
 i; }   }   

class Destination {     private
 String label;     Destination(String whereTo) { label 

= whereTo; }     String readLabel() { 


return label; }   }   
public static void
 main(String[] args) {     Parcel3 p 
= 

new Parcel3();     
//

 Must use instance of outer class     
//
 to create an instance of the inner class:    Parcel3.Contents c = p.new


 Contents();     Parcel3.Destination d = p.new
 Destination("Tasmania");   } } 
//

/:~

内部类和上塑造型

   在上塑造型到基类或者接口的时候,内部可可以完全隐藏他们自己,这种情况下只能获得接口或者基类的引用,而无法获得具体的对象类型。因为继承了基类或者接口的内部类,可以设置为外界不可见或不可用,这对于实现的隐藏非常有用。所有你获得的仅仅是一个对基类或者接口的引用:

//
: innerclasses/

class Parcel4 {   
private class
 PContents implements
 Contents {     

private int
 i = 11;     public
 int value() { return
 i; }   }   protected
 class PDestination implements Destination {     
private

 String label;     
private

 PDestination(String whereTo) {       label 
=

 whereTo;     }     public
 String readLabel() { return
 label; }   }   

public
 Destination destination(String s) {     

return new
 PDestination(s);   }   
public

 Contents contents() {     
return

 new PContents();   } } 
public class


 TestParcel {   public 
static void
 main(String[] args) {     Parcel4 p = new


 Parcel4();     Contents c = p.contents();     Destination d 
= p.destination("Tasmania");     
//

 Illegal -- can’t access private class:     
//

! Parcel4.PContents pc =  PContents();

  } } //
/:~

方法和作用域中的内部类

  内部类还可以定义在方法中,甚至是一个作用域中,这样做的原因有两点:首先,像前面所看到的,你需要继承某个接口,从而可以创建和返回某个引用;其次,当你需要解决某些复杂问题的时候,你在类中创建某些辅助对象,而这些对象并不许要对外可见。

  下面这个例子在方法中创建了一个内部类,我们也称之为本地内部类:

//
: innerclasses/ // Nesting a class within a method.

public class
 Parcel5 {   public
 Destination destination(String s) {     
class

 PDestination implements
 Destination {

      private
 String label;       private


 PDestination(String whereTo) {         label = whereTo;       }       
public String readLabel() { 
return

 label; }     }     
return

 new
 PDestination(s);   }   

public static
 void
 main(String[] args) {     Parcel5 p 

= new
 Parcel5();     Destination d 

= p.destination("Tasmania");   } } 
//

/:~

  下面的例子显示了在任意作用域内创建的内部类:

//
: innerclasses/ // Nesting a class within a scope.

public class
 Parcel6 {   private
 void internalTracking(boolean b) {     if
(b) {       class
 TrackingSlip {         
private

 String id;         TrackingSlip(String s) {           id 
= s;         }         String getSlip() { 
return

 id; }       }       TrackingSlip ts 
= new

 TrackingSlip("slip");       String s 
= ts.getSlip();     }     
//

 Can’t use it here! Out of scope:     
//

! TrackingSlip ts = new TrackingSlip("x");

  }   public
 void track() { internalTracking(
true

); }   public
 static void
 main(String[] args) {     Parcel6 p 
= new

 Parcel6();     p.track();   } } 
//

/:~

匿名内部类

  如下是匿名内部类的一种写法:

//
: innerclasses/ // Returning an instance of an anonymous inner class.

public class
 Parcel7 {   public
 Contents contents() {     
return

 new Contents() { //
 Insert a class definition

      private int
 i = 11;       
public

 int value() { return
 i; }     }; //
 Semicolon required in this case

  }   public
 static void
 main(String[] args) {     Parcel7 p 
= new

 Parcel7();     Contents c =
 p.contents();   } } //
/:~

其含义表示如下:

//
: innerclasses/ 
//

 Expanded version of 

public class
 Parcel7b {   class
 MyContents implements
 Contents {     

private int
 i = 11;     public
 int value() { return
 i; }   }   public
 Contents contents() { return 
new

 MyContents(); }   public
 static void
 main(String[] args) {     Parcel7b p 
= new

 Parcel7b();     Contents c =
 p.contents();   } } 

///:~

  当需要向匿名内部类传递初始化参数的时候可以使用如下的写法:

//
: innerclasses/ // Calling the base-class constructor.
 
public class
 Parcel8 {   public
 Wrapping wrapping(int
 x) {     

// Base constructor call:

    return new
 Wrapping(x) { //
 Pass constructor argument.

      public int
 value() {         
return super.value() * 47
;       }     }; //


 Semicolon required

  }   public
 static void
 main(String[] args) {     Parcel8 p 
= new

 Parcel8();     Wrapping w 
= p.wrapping(10

);   } } ///:~

  如果需要在匿名内部类中使用匿名内部类外部定义的对象,那么编译器需要在参数前面加上final关键字,如下:

//
: innerclasses/ // An anonymous inner class that performs 
//

 initialization. A briefer version of .

public class
 Parcel9 { //
 Argument must be final to use inside 
//

 anonymous inner class:

  public Destination destination(final String dest) {     
return new


 Destination() {       private
 String label = dest;       
public

 String readLabel() { return
 label; }     };   }   

public static
 void
 main(String[] args) {     Parcel9 p 

= new
 Parcel9();     Destination d 

= p.destination("Tasmania");   } } 
//

/:~

  以内匿名内部类没有名称,那么如何执行匿名内部类的初始化函数呢?可以通过instance initialization实例初始化来执行初始化的工作,如下:

//
: innerclasses/ 
//

 Creating a constructor for an anonymous inner class.

import static
 net.mindview.util.Print.*; 
abstract

 class Base {   
public Base(int
 i) {     print(
"Base constructor, i = " +

 i);   }   public 
abstract

 void f(); } 
public class
 AnonymousConstructor {   
public

 static Base getBase(int
 i) {     return
 new
 Base(i) {       { print(

"Inside instance initializer"); }       
public

 void
 f() {         print(

"In anonymous f()");       }     };   }   
public static
 void
 main(String[] args) {     Base base 

= getBase(47);     base.f();   } } 
/*

 Output: Base constructor, i = 47 Inside instance initializer In anonymous f() 
*///

:~

这里的i不用添加final关键字,因为它只是用来传递给基类的初始化函数,而在匿名内部类中并没有对他进行任何使用。

  下面是parcel例子的一个匿名内部类版本:

//
: innerclasses/ 
//

 Using "instance initialization" to perform 
//

 construction on an anonymous inner class.

public class
 Parcel10 {   public
 Destination destination(final
 String dest, final float
 price) {     return
 new
 Destination() {       

private int
 cost;       //
 Instance initialization for each object:

      {         cost 
= Math.round(price);         
if

(cost > 100)         System.out.println(
"Over budget!");       }       

private String label =
 dest;       public
 String readLabel() { 

return label; }     };   }   
public static
 

void main(String[] args) {     Parcel10 p 
= new Parcel10();


      Destination d = p.destination("Tasmania", 101.395F);   } } 
/* Output: Over budget! 
*///:~

从上面代码我们看到,可以将不能放在域中初始化的代码放到实例初始器中, 完成构造器的功能,但是实例构造器也有限制,它不能被重载,因此对于内部匿名类只能有一个构造其。另外一点还需要记住的是匿名内部类只能继承自来或者接口,不能同时继承类和接口,如果是继承接口的话,也只能继承自一个接口。

  下面我们就用匿名内部类来修改工厂方法:

//
: innerclasses/

import static
 net.mindview.util.Print.*; 
interface

 Service {   void
 method1();   void
 method2(); } interface
 ServiceFactory {   Service getService(); } 
class

 Implementation1 implements
 Service {   

private
 Implementation1() {}   

public void
 method1() {print("Implementation1 method1");}   


public void
 method2() {print("Implementation1 method2");}   
public

 static ServiceFactory factory = 
new

 ServiceFactory() {                                         


public Service getService() {                                           
return new

 Implementation1();                                         }                                       }; } 
class

 Implementation2 implements
 Service {   

private Implementation2() {}
   public
 void
 method1() {print("Implementation2 method1");}   

public void
 method2() {print("Implementation2 method2");}   
public

 static ServiceFactory factory = 
new

 ServiceFactory() {                                         
public
 Service getService() {                                           return
 new
 Implementation2();                                         }                                       }; } 
public

 class Factories {   
public static
 void
 serviceConsumer(ServiceFactory fact) {     Service s 

= fact.getService();     s.method1();     s.method2();   }   
public static
 void

 main(String[] args) {     serviceConsumer(Implementation1.factory);     
//
 Implementations are completely interchangeable:    serviceConsumer(Implementation2.factory);   } } 
/*
 Output: Implementation1 method1 Implementation1 method2 Implementation2 method1 Implementation2 method2 

*///:~

嵌套类

  如果不许要内部类与包含它的类有联系的话,可以使用嵌套类,也就是用s tatic修饰的内部类。一般的内部类总是包含一个包含它的外部类的引用,但是静态的内部类你需要记住两点:你不许要外部类来创建内部类的实例;在嵌套类内不你不能使用非静态的外部类对象。同时,一般内部类的域和方法只能通过外部ulei访问,因此一般内部类中不能有静态数据,静态域或嵌套类。但是在静态内部类中这些都可以存在:

//
: innerclasses/ 
//

 Nested classes (static inner classes).
public

 class Parcel11 {   
private static
 class ParcelContents 
implements

 Contents {     private
 int i = 11;     
public int
 value() { return
 i; }   }   

protected static
 class ParcelDestination 
implements
 Destination {     

private
 String label;     

private
 ParcelDestination(String whereTo) {       label 

= whereTo;     }     
public

 String readLabel() { return
 label; }     

//
 Nested classes can contain other static elements:

    public static
 void f() {}     
static int
 x = 10;     static
 class
 AnotherLevel {       

public static
 void f() {}       
static int
 x = 10;     }   }   
public

 static
 Destination destination(String s) {     

return new
 ParcelDestination(s);   }   
public

 static
 Contents contents() {     

return new
 ParcelContents();   }   
public

 static void
 main(String[] args) {     Contents c 
= contents();     Destination d 

= destination("Tasmania");   } } 


///:~

  另外,在一般内部类中可以使用this关键字来表示对外部类的引用,但是在静态内部类中没有类似与上面的this引用外部类的用法。

  一般来讲,接口中是不能有实现功能的代码的,但是在接口中可以有内部类,任何在接口中定义的类都是自动为public和static的。因为接口中的类是静态的,因此它并没有违反接口的规则,仅仅是在同一个命名空间下防止了一个嵌套类,这个静态的内部类还可以对周围的接口进行实现:

//
: innerclasses/ // {main: ClassInInterface$Test}

public interface
 ClassInInterface {   void
 howdy();   class
 Test implements
 ClassInInterface {     

public void
 howdy() {       System.out.println(
"Howdy!"

);     }     public
 static void


 main(String[] args) {       new


 Test().howdy();     }   } } /*
 Output: Howdy! *///


:~

  当你需要为接口的多种实现版本定义一些共同的实现代码的时候,使用接口内部类非常方便。

  不管嵌套类嵌套了多少个层次,在嵌套类中总是可以获取到这个嵌套层次中任何一个类的成员,如下:

//
: innerclasses/ 
//

 Nested classes can access all members of all 
//

 levels of the classes they are nested within.

class MNA {   
private void
 f() {}   class
 A {     private
 void g() {}     
public class
 B {       void
 h() {         g();         f();       }     }   } } 
public

 class
 MultiNestingAccess {   public
 static

 void
 main(String[] args) {     MNA mna = new


 MNA();     MNA.A mnaa = mna.new


 A();     MNA.A.B mnaab = mnaa.new


 B();     mnaab.h();   } } //


/:~

我们可以看到在MNAAB中调用方法g和f的时候不许要特殊的修饰,同时也示范了如何在多嵌套层次的类中如何创建不同层次上的对象,.new可以帮助获取正确的范围。

为何使用内部类

  为何Java的开发者要费劲心思创建出内部类的语法呢?通常内部类都是继承 自一个基类或者接口的,通常在内部类中对创建它的外部类对象进行操作。因此你可以说内部类提供了一个针对外部类的窗口。但是如果仅仅是为了获得对接口的引用,那么为什么不直接让外部类继承自这个接口呢?那么内部类 承和外部类继承有什么不同呢?答案是我们并不是总是要继承自接口,有时候我们需要继承自基类。因此使用内部类的最主要原因是:每个内部类都可以继承自一个基类,因此,使用内部类继承基类的时候不会受到外部类是否已经继承了某个基类的限制,本质上也就是可以实现多基类继承。

  当有两个接口需要某个类继承的时候,可以选择继承一个接口,然后在内 类继承另外一个接口,另外一种方法就是直接继承自这两个接口,选择哪个都可以实现你需要的功能;但是如果这两个不是接口,而是抽象类或者类呢?那么那么我们就必须选择第一种方法,继承自一个类,然后在内部类中继承自另外一个类,如下:

//
: innerclasses/ 
//

 With concrete or abstract classes, inner 
//

 classes are the only way to produce the effect 
//
 of "multiple implementation inheritance."package
 innerclasses; 

class D {}
abstract class
 E {} class
 Z extends
 D {   E makeE() { 

return new
 E() {}; } } public
 class
 MultiImplementation {   

static void
 takesD(D d) {}   static
 void takesE(E e) {}   
public static
 void

 main(String[] args) {     Z z 
= 

new Z();     takesD(z);     takesE(z.makeE());   } } 
///:~

  如果不许要解决多重:继承的问题,那么可以完全不许要内部类,但是使 了内部类的话你还可以获得其他的特点,如下:在外部类对象中可以创建多个内部类对象的实例,每个实例都有自己的信息,相互独立;在一个外部类中你可以定义多个内部类,每个继承自相同或不同的类;内部类的创建不依赖与外部类对象。

   闭包指的是保存了创建它的作用域信息的对象。从这个定义来看,内部类 就是一种闭包,内部类保存了对外部创建类的引用,并且可以引用所有的成员,即使是private修饰的成员。另外,Java中有一种类似与指针机制的参数使用称之为回调。通过回调可以在一些类中反向调用创建这个对象中的一些信息。但是Java中对指针的使用非常谨慎,因此在语言中并没有包含指针的概念。闭包可以有效地解决这个问题,如下面的代码:

//
: innerclasses/ 
//

 Using inner classes for callbacks

package innerclasses; 
import static
 net.mindview.util.Print.*; 
interface

 Incrementable {   void
 increment(); } //
 Very simple to just implement the interface:

class Callee1 implements
 Incrementable {   private
 int i = 0;   
public void
 increment() {     i++
;     print(i);   } } 

class MyIncrement {   
public void
 increment() { print("Other operation"); }   
static

 void
 f(MyIncrement mi) { mi.increment(); } } //


 If your class must implement increment() in //


 some other way, you must use an inner class:

class Callee2 extends
 MyIncrement {   private
 int i = 0;   
public void
 increment() {     super.increment();     i++
;     print(i);   }   

private class
 Closure implements
 Incrementable {     

public void
 increment() {       
//

 Specify outer-class method, otherwise       
//

 you’d get an infinite recursion:

      Callee2.this
.increment();     }   }   Incrementable getCallbackReference() {     return
 new Closure();   } } 
class Caller {   
private
 Incrementable callbackReference;   Caller(Incrementable cbh) { callbackReference 

= cbh; }   void
 go() { callbackReference.increment(); } } 
public

 class Callbacks {
   public
 static void
 main(String[] args) {     Callee1 c1 
= new

 Callee1();     Callee2 c2 = 
new

 Callee2();     MyIncrement.f(c2);     Caller caller1 
= new

 Caller(c1);     Caller caller2 
= new

 Caller(c2.getCallbackReference());     caller1.go();     caller1.go();     caller2.go();     caller2.go();   } } 
/*
 Output: Other operation 1 1 2 Other operation 2 Other operation 3 *///
:~

   内部类的另外一种用法就是控制框架,应用框架是指一个或者一系列类,能够处理一系列一般性的问题。在使用框架的时候通常继承或者扩展框架里面类从而解决特定的问题。控制框架主要是针对事件响应的系统,主要的应用场景有用户界面。

  首先我们创建一个事件基类:

//
: innerclasses/controller/ // The common methods for any control event.

package
 innerclasses.controller; public
 abstract

 class Event {   
private long
 eventTime;   protected
 final long
 delayTime;   public
 Event(long
 delayTime) {     

this.delayTime =
 delayTime;     start();   }   

public void
 start() { //
 Allows restarting    eventTime = System.nanoTime() + delayTime;   }   
public boolean
 ready() {     return
 System.nanoTime() >= eventTime;   }   
public

 abstract void
 action(); } //
/:~

下面是控制框架的主体部分,分离了不变和变化的部分,不便的部分已经封装到控制器内,变化的部分可以分散到不同的Event基类的派生类当中:

//
: innerclasses/controller/ 
//

 The reusable framework for control systems.

package
 innerclasses.controller; import
 java.util.*; 

public class
 Controller {   //
 A class from java.util to hold Event objects:

  private
 List<Event> eventList = new
 ArrayList<Event>();   

public void


 addEvent(Event c) { eventList.add(c); }   public
 void run() {     
while(eventList.size() > 0
)     

//
 Make a copy so you’re not modifying the list     

//
 while you’re selecting the elements in it:    for
(Event e : new

 ArrayList<Event>(eventList))       
if
(e.ready()) {         System.out.println(e);         e.action();         eventList.remove(e);       }   } } 
//

/:

这个时候就可以使用内部类了,使用内部类可以一方面将控制框架集中到一个类中,内部类可以用来扩展不同的action方法;另外一方面使用内部类可以方便的获得外部类的成员,从而更加容易理解,如下:

//
: innerclasses/ 
//

 This produces a specific application of the 
//

 control system, all in a single class. Inner 
//
 classes allow you to encapsulate different 

//
 functionality for each type of event.import
 innerclasses.controller.*

; public class
 GreenhouseControls extends
 Controller {   

private boolean
 light = false;   
public class
 LightOn extends
 Event {     

public LightOn(long
 delayTime) { super
(delayTime); }     

public void
 action() {       // Put hardware control code here to       
//

 physically turn on the light.

      light = true
;     }     public
 String toString() { return
 "Light is on"; }   }   

public class
 LightOff extends
 Event {     

public LightOff(long
 delayTime) { super
(delayTime); }     

public void
 action() {       // Put hardware control code here to       
//

 physically turn off the light.

      light = false
;     }     public
 String toString() { return
 "Light is off"; }   }   

private boolean
 water = false;   
public class
 WaterOn 

extends Event {     
public WaterOn(long
 delayTime) { 

super(delayTime); }     public void
 action() {       //


 Put hardware control code here.

      water = true
;     }     public


 String toString() {       return
 "Greenhouse water is on";     }   }   
public

 class WaterOff extends
 Event {     public
 WaterOff(long delayTime) { 
super

(delayTime); }     
public

 void
 action() {       

//
 Put hardware control code here.      water = false


;     }     public


 String toString() {       return
 "Greenhouse water is off";     }   }   
private

 String thermostat = "Day";   
public

 class ThermostatNight extends Event {     public
 ThermostatNight(long
 delayTime) {       

super
(delayTime);     }     

public void
 action() {       // Put hardware control code here.

      thermostat = "Night";     }     
public
 String toString() {       

return
 "Thermostat on night setting";     }   }   

public class
 ThermostatDay extends
 Event {     

public ThermostatDay(long
 delayTime) {       
super
(delayTime);     }     

public void
 action() {       // Put hardware control code here.

      thermostat = "Day";     }     
public
 String toString() {       

return
 "Thermostat on day setting";     }   }   

//
 An example of an action() that inserts a   

//
 new one of itself into the event list:  public
 class

 Bell extends
 Event {     

public Bell(long
 delayTime) { super
(delayTime); }     

public void
 action() {       addEvent(new Bell(delayTime));     }     
public

 String toString() { return
 "Bing!"; }   }   
public

 class Restart extends


 Event {     private
 Event[] eventList;     public
 Restart(long
 delayTime, Event[] eventList) {       

super
(delayTime);       

this.eventList =
 eventList;       

for
(Event e : eventList)       addEvent(e);     }     

public void
 action() {       
for

(Event e : eventList) {         e.start(); 
//

 Rerun each event

        addEvent(e);       }       start(); 
// Rerun this Event

      addEvent(this
);     }     public


 String toString() {       return
 "Restarting system";     }   }   
public

 static class
 Terminate extends
 Event {     

public Terminate(long
 delayTime) { super
(delayTime); }     

public void
 action() { (0); }     
public

 String toString() { return
 "Terminating"; }   } } 

///:~

下面是对控制框架的使用:

//
: innerclasses/Greenhouse 
//

 Configure and execute the greenhouse system. 
//

 {Args: 5000}

import innerclasses.controller.*
; public class
 GreenhouseController {   
public

 static void
 main(String[] args) {     GreenhouseControls gc 
= new

 GreenhouseControls();     
// Instead of hard-wiring, you could parse     
//
 configuration information from a text file here:    gc.addEvent(gc.new
 Bell(900));     Event[] eventList = {       gc.
new ThermostatNight(0
),       gc.

new LightOn(200
),       gc.

new LightOff(400
),       gc.

new WaterOn(600
),       gc.

new WaterOff(800
),       gc.

new ThermostatDay(1400
)     };     gc.addEvent(gc.

new Restart(2000
, eventList));     

if(args.length == 1
)       gc.addEvent(new


 GreenhouseControls.Terminate(new
 Integer(args[0

])));     ();   } } /*


 Output: Bing! Thermostat on night setting Light is on Light is off Greenhouse water is on Greenhouse water is off Thermostat on day setting Restarting system Terminating 
*///:~

内部类继承

  因为内部类的构造器必须引用包含它的外部类对象,因此在继承内部类的时候有一点点复杂。因此对与外部类的实例必须在派生类中初始化,因为在派生类中没有默认的外部类的实例,因此必须显示初始化:

//
: innerclasses/ 
//

 Inheriting an inner class.

class WithInner {   
class Inner {} } 
public class
 InheritInner extends
 WithInner.Inner {   

//! InheritInner() {} 
// Won’t compile

  InheritInner(WithInner wi) {     wi.
super();   }   
public static
 void

 main(String[] args) {     WithInner wi 
= new
 WithInner();     InheritInner ii 

= new
 InheritInner(wi);   } } 

///:~

内部类是否能够重写

  如果要扩展外部类,继承之后重写内部类,会怎么样呢?

//
: innerclasses/ //
 An inner class cannot be overriden like a method.

import static
 net.mindview.util.Print.*; 
class

 Egg {   private
 Yolk y;   
protected class
 Yolk {     public
 Yolk() { print("Egg.Yolk()"); }   }   
public

 Egg() {     print(
"New Egg()");     y 

= new
 Yolk();   }
}
public class BigEgg extends Egg {   public class Yolk {     public Yolk() { print("BigEgg.Yolk()"); }   }    public static void main(String[] args) {      new BigEgg();   } } /* Output: New Egg() Egg.Yolk() */// :~

我们可以看到继承外部类并且重写内部类实际上并没有做任何事情。下面的例子告诉我们继承外部类并且重写内部类的时候,两个内部类是分开的尸体,各有自己的命名空间,但是可以显式的继承内部类:

//
: innerclasses/ // Proper inheritance of an inner class.

import static
 net.mindview.util.Print.*; 
class

 Egg2 {   protected
 class Yolk {     
public
 Yolk() { print("Egg2.Yolk()"); }     

public void
 f() { print("Egg2.Yolk.f()");}   }   


private Yolk y = new
 Yolk();   public
 Egg2() { print("New Egg2()"); }   
public 

void insertYolk(Yolk yy) { y = yy; }   
public void


 g() { y.f(); } } public 
class

 BigEgg2 extends Egg2 {   
public class
 Yolk extends
 Egg2.Yolk {     

public
 Yolk() { print("BigEgg2.Yolk()"

); }     public 
void

 f() { print("BigEgg2.Yolk.f()"); }   }   
public BigEgg2() { insertYolk(
new

 Yolk()); }   public
 static void


 main(String[] args) {     Egg2 e2 = new
 BigEgg2();     e2.g();   } } 
/*

 Output: Egg2.Yolk() New Egg2() Egg2.Yolk() BigEgg2.Yolk() BigEgg2.Yolk.f() 
*///

:~

本地内部类

  之前提到过内部类可以定义在语句块中,通常是在方法体中。一个本类内部类不能拥有可见性标识,因为它不是外部类的一部分,但是它能够获取到当前语句块中的final变量和外部类的所有成员:

//
: innerclasses/ 
//

 Holds a sequence of Objects.

import static
 net.mindview.util.Print.*; 
interface

 Counter {   int
 next(); } public
 class LocalInnerClass {   
private int
 count = 0;   Counter getCounter(
final

 String name) {     //
 A local inner class:

    class LocalCounter 
implements Counter {       
public
 LocalCounter() {         

//
 Local inner class can have a constructor        print("LocalCounter()");       }       
public int
 next() {         printnb(name); 
//

 Access local final

        return count++
;       }     }     return
 new
 LocalCounter();   }   

//
 The same thing with an anonymous inner class:  Counter getCounter2(final


 String name) {     return
 

new Counter() {       


// Anonymous inner class cannot have a named       
//
 constructor, only an instance initializer:      {         print(
"Counter()");       }       
public

 int
 next() {         printnb(name); 

// Access local final

        return count++
;       }     };   }   public
 static void
 main(String[] args) {     LocalInnerClass lic 
= new

 LocalInnerClass();     Counter c1 
= lic.getCounter("Local inner "),          c2 

= lic.getCounter2("Anonymous inner ");     
for(int
 i = 0; i < 5; i++)       print(());     
for

(int i = 0; i < 5; i++)
       print(());   } } 
/*


 Output: LocalCounter() Counter() Local inner 0 Local inner 1 Local inner 2 Local inner 3 Local inner 4 Anonymous inner 5 Anonymous inner 6 Anonymous inner 7 Anonymous inner 8 Anonymous inner 9 

*///:~

因为本地内部类不能在方法外部使用,因此使用本地内部类而不使用匿名内部类的原因是你是否需要构造其或者重载的构造其,因为匿名内部类只能使用实例化初始。

内部类标识

   每个类编译之后都会产生一个.clas s文件,里面包含了对象的相关信息,那么内部类呢,是否也是一个单独的clas文件呢?是的,但是文件的名称有着严格的格式,是外部类名称加上$再加上内部类的名称,例如上面的文件编译后产生如下class文件:

Counter.class
LocalInnerClass$l.class
LocallnnerClassSlLocalCounter.class
LocallnnerClass.class
如果内部类是匿名的,那么编译器仅仅是用数字表示匿名内部类的名称,如果有嵌套的内部类,那么将直接在后面继续添加$和内部类的名称即可。

资源下载