TIJ-4Edition-内部类

1、创建和实例化内部类

  可以将一个类的定义放在另一个类的内部,这就是内部类。

  把类的定义放在外围类的里面,这就创建了一个内部类。

  内部类持有指向其外围类的引用,这是在编译时自动添加上去的。

  所以,内部类自动拥有对其外围类的所有成员的访问权限(包括private成员)。

  可以 .this获取内部类引用,用 .new 创建内部类。

Outer.Inner inner=Outer.new Inner();

  除了嵌套类(静态内部类),创建内部类都要先创建外围类对象。

  使用内部类,可以完全隐藏接口的实现(使用private内部类实现接口)。

  可以在方法里面或者任意的作用域内定义内部类。

  普通内部类不能包含静态的数据和字段。但是嵌套类可以。

2、匿名内部类 

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

public class Parcel7 {
  int initValue;
  public Contents contents(initValue) {
    return new Contents(initValue) { // 创建一个继承自Contents的匿名内部类 initValue为基类构造器传参
      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();
  }
} ///:~

3、匿名内部类与工厂方法模式

  使用匿名内部类时,工厂方法模式就可以实现得更加的优雅了。

  类和它的工厂方法可以写到一起了。

//: innerclasses/Factories.java
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 *///:~

 4、嵌套类——静态内部类

  嵌套类和它的外围类没有联系(没有外围类的引用)。

  创建嵌套类并不需要外围类对象。

  不能从嵌套类中访问非静态的外围类对象。

  嵌套类可以置于接口内部(static),甚至可以实现外围接口!

5、使用内部类

  1、使用内部类实现类的多重继承

    内部类和外部类的继承是独立的,它们可以各自继承其他类。

class C{}
class D {}
abstract class E {}

class Z extends D {
    class Inner extends C{} //普通内部类
    E makeE() {
        return new E() {}; //匿名类
    }
}

 

  2、使用内部类实现闭包与回调

    闭包(closure)是一个可调用对象,它记录了来自创建它的作用域的信息。

    由于内部类可以访问其外围类的所有变量,它是一个很好的闭包。

//: innerclasses/Callbacks.java
// 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 *///:~

  

  3、 内部类与控制框架

    模板方法设计模式:

      模板方法设计模式属于行为型。

      模板方法包含算法的基本结构,并且会调用一个或多个可覆盖的方法,以完成算法的动作。

      将变化的事物和保持不变的分开,模板方法中,算法的基本框架是固定的,可覆盖的方法是变化的。

      在通常的实现中,一个抽象类公开定义了执行它的方法的方式/模板,

      它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。

    命令模式:

      命令模式是数据驱动的设计模式,属于行为型模式。

      请求以命令的方式封装在对象内,并传递给调用对象,调用对象查找能处理它的合适的对象,

      并把命令传给这个合适对象,由它来执行命令。

    下面是一个温室控制器的例子:

      事件被定义为了抽象类,子类实现它来定义不同的事件。

      控制器是基于事件进行相应的,调用对应事件的处理方法来处理它。

/**
* 事件的抽象类
* 每个事件都包括:延迟时间,执行时间以及执行的动作
* 其中执行动作是变化的,因此设计为抽象方法,子类必须实现
* 这也是模板方法设计模式的应用之一
*/
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();
}

/**
* 控制器实现
* 控制器中维护了一个事件列表
* 控制器遍历该列表,如果有事件可以执行,就运行事件的方法来执行它
* 事件被封装为了一个对象,该对象中包含了事件的响应方法。
* 控制器中的事件决定了它的行为,这是事件响应系统的实现。
* 这也是命令模式的实现
*/
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);
        }
  }
}

//: innerclasses/GreenhouseControls.java
// 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.

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() { System.exit(0); }
    public String toString() { return "Terminating";  }
  }
}

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])));
    gc.run();
  }
} 
/* 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
*/

 

 

6、继承、覆盖内部类

  内部类可以被继承嘛?

  可以,但是,构造器中必须提供外部类的引用,毕竟,内部类是依托于外部类而存在的嘛。

  这样说,继承静态内部类就可以直接继承咯。——对的

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);
  }
}

  如果内部类是静态的:

class WithInner {
    static class Inner {}
}

public class InheritInner extends WithInner.Inner {
    InheritInner() {} // compile

    public static void main(String[] args) {
        
        InheritInner ii = new InheritInner();
    }
} 

 

  

  继承一个带有内部类的类时,在派生类重新定义和基类内部类同名的内部类时,基类的内部类会被覆盖嘛?

  不会,它们是完全独立的,各在自己的名称空间内(毕竟绑定的外部类对象都不一样)。

//: innerclasses/BigEgg.java
// 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()
*///:~

 

  

      

 

posted @ 2021-09-17 12:48  Lqblalala  阅读(37)  评论(0编辑  收藏  举报