闭包(Closure)是一种能被调用的对象,它保存了创建它的作用域信息,java7虽然没有显式的支持闭包,但对于非静态内部类而言,它不仅记录了其外部类的详细信息,还保留了一个创建非静态内部类对象的引用,并且可以直接调用外部类的private成员,因此可以把非静态被不累当成面向对象领域的闭包。
通过这种方必报的非静态内部类,可以很方便地实现回调功能,回调就是某个方法一旦获得了内部类对象的引用来调用其外部类的方法,这是一种非常灵活的功能。
interface Teachable { void work(); } public class Programmer { private String name; //Programmer类的两个构造器 public Programmer(){} public Programmer(String name) { this.name = name; } //此处省略了name的setter和getter方法 public void setName(String name) { this.name = name; } public String getName() { return this.name; } public void work() { System.out.println(name + "在灯下认真敲键盘..."); } }
假如有一个人既是一个程序员又是一个教师,于是就需要一个特殊的类,既需要实现Teachable接口,也需要继承Programmer父类。表面上看起来没什么问题,问题是Teachable接口和Programmer父类里包含了相同的work方法。
这个时候,我们就可以通过一个仿闭包的内部类来实现这个功能。
public class TeachableProgrammer extends Programmer { public TeachableProgrammer(){} public TeachableProgrammer(String name) { super(name); } //教学工作依然由TeachableProgrammer类定义 private void teach() { System.out.println(getName() + "教师在讲台上讲解..."); } private class Closure implements Teachable { /* 非静态内部类回调外部类实现work方法,非静态内部类引用的作用仅仅是 向客户类提供一个回调外部类的途径 */ public void work() { teach(); } } //返回一个非静态内部类引用,允许外部类通过该非静态内部类引用来回调外部类的方法 public Teachable getCallbackReference() { return new Closure(); } }
下面程序示范了如何让让TeachableProgrammer对象既执行“教学”的work方法,也执行“编程”的work方法。
public class TeachableProgrammerTest { public static void main(String[] args) { TeachableProgrammer tp = new TeachableProgrammer("李刚"); //直接调用TeachableProgrammer类从Programmer类继承到的work方法 tp.work(); //表面上调用的是Closure的work方法, //实际上是回调TeachableProgrammer的teach方法 tp.getCallbackReference().work(); } }
上面程序中加粗字部分,表面上调用了Teachable对象(实际上是Closure对象)的work方法,实际上回调了TeachableProgrammer对象的teach方法。内部类对象可以很方便地回调其外部类的Field、方法,这样就可以让编程更加灵活。