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() *///:~
标签:4Edition,内部,void,public,delayTime,TIJ,new,class,Event 来源: https://www.cnblogs.com/lqblala/p/15171096.html