2011年写的一个测试java闭包的实例,在事件监听中用得比较多的设计模式!
闭包的特性
1.闭包的价值在于可以作为函数对象或者匿名函数,持有上下文数据,作为第一级对象进行传递和保存。
2.闭包广泛用于回调函数、函数式编程中。
3.函数可以访问函数外部的变量,并且与它建立联系,可以修改变量和读取到外部对变量的修改。
定义一个接口,通过接口来传递方法体
- /**
- * 回调函数
- * 可以作为参数传给方法
- */
- public interface Action{
-
- public void excute(Object arg);
-
- }
消息接收类
/**
* 消息接收
* 一个常规的属性和方法封装类
*/
public class To{
private int j = 0;
public void update(Object i) {
//持有To的上下文
j = (Integer) i;
System.out.println(j);
}
}
消息发出者
有一个参数是接口的方法,接口的方法参数是From类的上下文。
public class From{
private int i = 12112;
public void doWork(final Action action){
//do sth
action.excute(i);
}
}
测试主方法
实际上是Java中的回调场景,只是回调方法中同时具备方法实现的地方和方法执行的地方上下文。
public static void main(String[] args) {
final To to = new To();
From from = new From();
from.doWork(new Action() {
@Override
public void excute(Object arg) {
System.out.println("传方法");
to.update(arg);
}
});
}
Java无语法级的闭包特性支持,但通过匿名内部类作为参数传递的情况下,做到了保留其外部类的详细信息,还保留了一个创建非静态内部类对象的引用,并且可以直接调用外部类的private成员,因此可以把非静态内部类当成面向对象领域的闭包。
通过这种仿闭包的非静态内部类,可以很方便地实现回调功能,回调就是某个方法一旦获得了内部类对象的引用后,就可以在合适时候反过来调用外部类的方法。所谓回调,就是允许客户类通过内部类引用来调用其外部类的方法,这是一种非常灵活的功能。
闭包实质是作用域或者上下文的直接传递,而非Java中值和引用的这种参数传递。
我们知道计算机程序设计语言经历过三种模式的变迁(来自架构简洁之道这本书的描述):
1.面向过程编程(结构化编程)
对程序控制权的直接转移进行了限制和规范,比如使用if/else/switch/while/for等各类面向过程的编程结构,但是约束goto的使用。
2.面向对象编程
对程序控制权的间接转移进行了限制和规范, 比如变量和函数封装成类,多态机制控制函数指针的动态变化。
3.函数式编程
对程序中的赋值进行了限制和规范。λ演算衍生而来,核心思想,不可变性。对应现在闭包中提到的函数传递。