能够将一个类定义放在另外一个类的定义内部,这就是内部类。java
建立内部类就是把类的定义置于外部类里面。闭包
public class Parcell { class contents{ int i=0; public void GetI(){ System.out.println("contents"+i); i++; } } class Destintion{ private String label; public void GetI(String s){ System.out.println(s); } } public contents GetontentsC(){ return new contents(); } public void ship(String dest){ contents c=new contents(); c.GetI(); Destintion d=new Destintion(); d.GetI(dest); } public static void main(String[] args){ Parcell p=new Parcell(); p.ship("dwdwdw"); Parcell.contents c=p.GetontentsC(); c.GetI(); } }
若是想从外部类的非静态方法以外的任意位置建立某个内部类的对象,那么必须具体的指明这个对象的类型:OuterClassName.InnerClassName.app
当生成一个内部类对象时,此对象和制造它的外围对象之间有一种联系,全部,它能访问它外围对象的全部成员,而不须要特殊条件。框架
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; } public class SequenceSelector implements Selector{ private int i=0; @Override public boolean end() { if (i==items.length) return false; return true; } @Override public Object current() { return items[i]; } @Override 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 s=sequence.selector(); while (s.end()){ System.out.print(s.current()); s.next(); } } } interface Selector{ boolean end(); Object current(); void next(); }
当外围类对象建立一个内部类对象时,此内部类会秘密捕获一个指向外围类对象的引用,而后,在你访问此外围类成员时,就用那个引用来选择外围类成员ide
若是须要生成对外部类对象的引用,可使用外部类的名字后面紧跟.this,这样产生的引用自动具备正确的类型。this
public class DotThis { void f(){ System.out.println("DotThis.f()"); } public class Inner{ public DotThis outer(){ return DotThis.this; } } public Inner inner(){ return new Inner(); } public static void main(String[] args){ DotThis d=new DotThis(); DotThis.Inner in=d.inner(); in.outer().f(); } }
建立某个内部类对象时,须要使用.new。编码
public class Parcel3 { class Contents{ private int i=11; public int value(){return i;} } public class Destination{ private String label; Destination(String whereTo){ label=whereTo; } String readLabel(){ return label; } } public static void main(String[] args){ Parcel3 p=new Parcel3(); Parcel3.Contents c=p.new Contents(); Parcel3.Destination d=p.new Destination("123"); System.out.println(d.label); } }
当将内部类向上转型为基类,尤为是一个接口的时候,内部类就颇有用了。由于内部类的某个接口的实现是能够彻底不可见而且不可用的。设计
public class TestParcel { public static void main(String[] args) { Parcel4 p = new Parcel4(); Contents c = p.contents(); Destination d = p.destination("tasmaina"); } } interface Destination { String readLabel(); } interface Contents { int value(); } class Parcel4 { private class PContents implements Contents { private int i = 11; @Override public int value() { return i; } } protected class PDestionation implements Destination { private String label; private PDestionation(String whereTo) { label = whereTo; } @Override public String readLabel() { return null; } } public Contents contents() { return new PContents(); } public Destination destination(String s){ return new PDestionation(s); } }
PDestination是protected,因此只要Parce4及其子类,还有与Parce4同一个包中的类能访问PDestination。
private内部类给类设计者提供了一条途径,经过这种方式,能够彻底阻止任何依赖于类型的编码,而且彻底隐藏实现细节。code
在方法的做用域内,建立一个完整的类对象
public class Parcel5 { public Destination destination(String s){ class PDestination implements Destination{ private String label; private PDestination(String whereTo){ System.out.println(whereTo); label=whereTo; } @Override public String readLabel() { return label; } } return new PDestination(s); } public static void main(String[] args){ Parcel5 p=new Parcel5(); Destination d=p.destination("sa"); } }
在任意的做用域嵌入一个内部类
public class Parcel6 { private void internalTracking1(boolean b) { if (b) { class TrackingSlip { private String id; TrackingSlip(String s) { id = s; System.out.println(id); } String getSlip() { return id; } } TrackingSlip trac=new TrackingSlip("asd"); // TrackingSlip ts = new TrackingSlip("slip"); //String s = ts.getSlip(); } } public void track() { internalTracking1(true); } public static void main(String[] args){ Parcel6 p=new Parcel6(); p.track(); } }
TrackingSlip类被嵌入在if语句的做用域内,这不是说该类建立是有条件的,它其实与别的类一块儿编译过。可是在TrackingSlip的做用域以外,它是不可用的。
public class Parcel7 { public Contents contents(){ return new Contents() { private int i=11; @Override public int value() { System.out.println(i); return i; } }; } public static void main(String[] args){ Parcel7 p7=new Parcel7(); p7.contents().value(); } }
contents()方法将返回值的生成与表示这个返回值的类的定义结合在一块儿。
经过new表达式返回的引用被自动向上转型。
public class Parcel7b { class ABContents implements Contents{ private int i=11; @Override public int value() { System.out.println(i); return i; } } public Contents contents(){ return new ABContents(); } public static void main(String[] args){ Parcel7b b=new Parcel7b(); Contents c=b.contents(); c.value(); } }
下面的基类须要一个有参数的构造器
public class Parcel8 { public Wrapping wrapping(int i){ return new Wrapping(i){ }; } public static void main(String[] args){ Parcel8 p8=new Parcel8(); Wrapping wr=p8.wrapping(7); } } class Wrapping{ public Wrapping(int i){ System.out.println(i); } }
Wrapping只是一个具备具体实现的普通类,但它仍是被其导出类看成公共"接口"来使用。
在匿名内部类尾部的分号,不是用来标记内部类结束的,它标记的是表达式的结束,只不过这个表达式正好表示匿名类。
若是定义一个匿名内部类,并但愿它使用一个外部定义的对象,那么就要求参数引用是final的。
public class Parcel9 { public Destination wrapping(final int i){ return new Destination(){ private int label=i; @Override public String readLabel() { System.out.println(label); return "i"; } }; } public static void main(String[] args){ Parcel9 p9=new Parcel9(); Destination wr=p9.wrapping(4); wr.readLabel(); } }
在匿名类中不可能有命令构造器,但经过实例初始化,就可以达到为匿名内部类建立一个构造器的效果。
public class Parcel8 { public Wrapping wrapping(int i){ return new Wrapping(i){ {System.out.println(i+1);} }; } public static void main(String[] args){ Parcel8 p8=new Parcel8(); Wrapping wr=p8.wrapping(7); } } class Wrapping{ public Wrapping(int i){ System.out.println(i); } }
匿名内部类与正规的继承相比有些受限,由于匿名类既能够扩展类,也能够是实现接口,但不能二者兼备,若是是实现接口,也只能实现一个。
优先使用类而不是接口。若是设计里面须要某个接口,那么必须了解它。
若是不须要内部类对象与其外围对象有联系,可使用内部类声明为static。这称为嵌套类。
普通的内部类对象隐试地保存了一个引用,指向建立它的外围类对象。当内部类是static的时,就不是这样的了。
嵌套类意味着:
普通内部类的字段与方法,只能放在类的外部层次上,全部普通的内部类不能有static数据和static字段,也不能包含嵌套类。
public class Parcel11 { private static class parceContents implements Contents{ @Override public int value() { return 0; } } public static Contents contents(){ return new parceContents(); } public static void main(){ Contents c=contents(); } }
在一个普通的内部类中,经过一个特殊的this引用能够连接到其外围类对象,嵌套类就没有这个特殊的this引用,这使得它相似一个static方法。
正常状况下,不能再接口中放置任何代码,但嵌套类能够做为接口的一部分,放到接口中的任何类都自动是public和static的。
public interface ClassInInterface { void howdy(); class Test implements ClassInInterface{ @Override public void howdy() { System.out.println("howdy"); } public static void main(String[] args){ new Test().howdy(); } } }
若是想要建立谋和代码,使得它们能够被某个接口的全部不一样实现所公用,那么使用接口内部的嵌套类会显得很方便。
一个内部类被嵌套多少层,它都能透明的访问全部它所嵌入的外围类对象。
class MNA { private void f(){System.out.println("f");} class A{ private void g(){System.out.println("g");} public class B{ void h(){ g(); f(); } } } } public class Multi{ public static void main(String[] args){ MNA mna=new MNA(); MNA.A maa=mna.new A(); MNA.A.B maab=maa.new B(); maab.h(); } }
.new 语法能参数正确的做用域,全部没必要再调用构造器时限定类名。
内部类继承自某个类或实现某个接口,内部类的代码操做建立它外围类的对象,全部能够认为内部类提供了某种进入外围类的接口。
每一个内部类都能独立地继承自一个实现,全部不管外围类是否已经继承了某个实现,对于内部类都没有影响。
在一个类中,以某种形式实现两个接口,有两种选择:使用单一类,或者使用内部类。
可是对于抽象类或者具体的类,就只能使用内部类实现多重继承了。
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()); } } class D { } abstract class E { } class Z extends D { E makeE() { return new E() { }; } }
闭包是一个可调用对象,它记录了一些信息,这些信息来自于建立它的做用域,经过这个定义,能够看出内部类是面向对象的闭包,由于它不只包含外围类对象的信息,还自动拥有一个指向此外围类对象的引用,在此做用域内,内部类有权操做全部成员,包括private成员。
经过回调,对象可以携带一些信息,这些信息容许它在稍后某个时刻调用初始的对象。
经过内部类实现回调:
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(); } } interface Incrementable{ void increment(); } class Callee1 implements Incrementable{ private int i=0; @Override public void increment() { i++; System.out.println(i); } } class MyIncrement{ public static int i=1; public void increment(){ System.out.println("Other operation"); } public static void f(MyIncrement mi){ mi.increment(); } } class Callee2 extends MyIncrement{ private int i=0; public void increment(){ super.increment(); i++; System.out.println(i); } private class Closure implements Incrementable{ @Override public void increment() { Callee2.this.increment(); } } Incrementable getCallbackReference(){ return new Closure(); } } class Caller{ private Incrementable callbackReference; Caller(Incrementable cbh){ callbackReference=cbh; } void go(){callbackReference.increment();} }
应用程序框架就是被设计用以解决某类特定问题的一个类或一组类。要应用某个应用程序框架,一般是继承一个或多个类,并覆盖某些方法。在覆盖后的方法中,编写代码定制应用程序框架提供的通用解决方案,以解决特定的问题。
控制框架是一类特殊的应用程序框架,它用来解决响应事件的需求。主要用来响应事件的系统被称为事件驱动系统。
首先,接口描述了要控制的事件:
public abstract class Event { private long eventTime; protected final long delayTime; public Event(long delayTime){ this.delayTime=delayTime; start(); } public void start(){ eventTime=System.nanoTime()+delayTime; } public boolean ready(){ return System.nanoTime()>=eventTime; } public abstract void action(); }
触发事件的实际控制框架:
import java.util.ArrayList; import java.util.List; public class Controller { private List<Event> eventList=new ArrayList<Event>(); public void addEvent(Event c){ eventList.add(c); } public void run(){ while (eventList.size()>0){ for (Event e:new ArrayList<Event>(eventList)) { if (e.ready()){ System.out.println(e); e.action(); eventList.remove(e); } } } } }
在如今的设计中,咱们还不知道Event到底作了什么。可是这个设计关键就是使变化的事物与不变的事物相互分离。而这就是内部类要作的事情。
内部类容许:
public class GreenhouseControls extends Controller { private boolean light = false; public class LightOn extends Event { public LightOn(long delayTime) { super(delayTime); } @Override public void action() { light = true; } public String toString() { return "Light is on"; } } public class LightOff extends Event { public LightOff(long delayTime) { super(delayTime); } @Override public void action() { light = false; } public String toString() { return "Light is off"; } } 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(); addEvent(e); } start(); addEvent(this); } public String toString() { return "Restarting system"; } } public static void main(String[] args){ GreenhouseControls gc=new GreenhouseControls(); Event[] eventList={ gc.new LightOn(20000), gc.new LightOff(40000) }; //gc.addEvent(gc.new LightOn(20000)); //gc.addEvent(gc.new LightOff(40000)); gc.addEvent(gc.new Restart(200000,eventList)); gc.run(); } }
内部类的构造器必须链接到指向其外围类对象的引用,因此在继承内部类的时候,那个指向外围类对象的秘密的引用必须被初始化,而在导出类中,再也不存在可链接的默认对象。
public class InheritInner extends WithInner.Inner{ InheritInner(WithInner wi){//必须指向一个外围对象的引用 wi.super(); } public static void main(String[] args){ WithInner wi=new WithInner(); InheritInner i=new InheritInner(wi); } } class WithInner{ class Inner{} }
public class BigEgg extends Egg{ public class Yolk{ public Yolk(){ System.out.println("BigEgg.Yolk()"); } } public static void main(String[] args){ new BigEgg(); } } class Egg{ private Yolk y; protected class Yolk{ public Yolk(){System.out.println("Egg.Yolk()");} } public Egg(){ System.out.println("New Egg()"); y=new Yolk(); } }
当继承了某个外围类时,内部类并无发生变化,这两个内部类是彻底独立的个体,各自在各自的命名空间内。
public class BigEgg2 extends Egg2 { public class Yolk extends Egg2.Yolk { public Yolk() { System.out.println("BigEgg2.Yolk()"); } public void f() { System.out.println("BigEgg2.Yolk.f()"); } } public BigEgg2() { insertYolk(new Yolk()); } public static void main(String[] args) { Egg2 e2 = new BigEgg2(); e2.g(); } } class Egg2 { protected class Yolk { public Yolk() { System.out.println("Egg2.Yolk()"); } public void f() { System.out.println("Egg2.Yolk.f()"); } } private Yolk y = new Yolk(); public Egg2() { System.out.println("New Egg2()"); } public void insertYolk(Yolk yy) { y = yy; } public void g() { y.f(); } }
public class LocalInnerClass { private int count=0; Counter getCounter(final String name) { class LocalCounter implements Counter { public LocalCounter() { System.out.println("LocalCounter()"); } @Override public int next() { System.out.print(name); return count++; } } return new LocalCounter(); } Counter getCounter2(final String name) { return new Counter() { { System.out.println("Counter()"); } @Override public int next() { System.out.print(name); 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++) System.out.println(c1.next()); for (int i=0;i<5;i++) System.out.println(c2.next()); } } interface Counter { int next(); }