上一篇:Java 匿名内部类
闭包(closure) 是一个可调用的对象,它记录了一些信息,这些信息来自于它创建的作用域。通过这个定义,Java 的内部类其实就是面向对象的闭包,因为它不仅包含外围类对象(创建内部类的作用域)的信息,还自动拥有一个指向此外围类对象的引用,在此作用域内,内部类有权操作所有的成员,包括private 成员。回调是一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口。通过回调对象能够携带一些信息,这些信息能允许它在稍后的某个时刻调用初始的对象。下面这个例子就是一个基于内部类与回调的案例(如果你现在理解起来有点难度,建议你把这个案例写一遍,一步一步运行看输出的结果):
interface Incrementable{
void increment();
}
/**
* 实现Incrementable 接口,实现increment() 方法
*/
class Callee1 implements Incrementable{
private int i = 0;
@Override
public void increment() {
i++;
System.out.println("implements Incrementable ...." + i);
}
}
class MyIncrement{
public void increment(){ System.out.println("Other Operation"); }
static void f(MyIncrement mi){ mi.increment();}
}
/**
* 继承MyIncrement 类,重写increment() 方法
* 并定义一个内部类Closure 实现了Incrementable 接口,实现了其中increment() 方法,
* 该方法调用了Callee2 中重写的increment() 方法
* getCallbackReference() 方法返回了Incrementable 接口的一个实现类Closure
*/
class Callee2 extends MyIncrement{
private int i = 0;
public void increment(){
super.increment(); //调用父类的构造函数
i++;
System.out.println("extends MyIncrement ...." + i);
}
private class Closure implements Incrementable{
@Override
public void increment() {
Callee2.this.increment(); //调用Callee2 的increment 方法
}
}
public Incrementable getCallbackReference(){
return new Closure();
}
}
class Caller{
private Incrementable callbackReference;
Caller(Incrementable incrementable){
callbackReference = incrementable;
}
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();
}
}
输出
Other Operation
extends MyIncrement ….1
implements Incrementable ….1
implements Incrementable ….2
Other Operation
extends MyIncrement ….2
Other Operation
extends MyIncrement ….3
内部类Closure 实现了Incrementable ,以提供一个返回Callee2 的钩子(hook),而且是一个安全的钩子。无论谁获得此 Incrementable 的引用,都只能调用increment(),除此之外没有任何其他功能。回调的机制在于它的灵活性,可以动态的在运行时决定要调用的方法。GUI 中的很多功能实现,到处都使用了回调。
最近只是在《Java 编程思想》内部类这一章节看到了这个有关闭包和回调的概念。也只是通过上面这个例子有了一些浅显的认识,日后如果有涉及到这方面的知识再来补充。
参考书籍:
《Java 编程思想》Bruce Eckel 著 陈昊鹏 译