闭包对于从函数式编程启蒙的童靴估计会很好理解,但是对于从JAVA这类纯粹OO启蒙的童靴,估计会比较困难。对于支持闭包的多数语言来说,函数都是作为第一级的对象,这就意味着:闭包可以被当做参数传递给函数,可以存储到变量中,也可以作为返回值。
那么什么是闭包?
闭包的定义是这样的:可以包含自由(未绑定)变量的代码块,这些变量不是在这个代码块或者任何全局上下文中定义的,而是在定义代码块的环境中定义。闭包一词来源于以下两者的结合:要执行的代码块(由于自由变量的存在,相关变量引用没有释放)和为自由变量提供绑定的计算环境(作用域)。
是不是很晦涩?
换句比较不那么折磨人的话说就是:闭包是一个可以引用外部作用域的变量,可以用作参数的代码块。
闭包形式上跟函数很像,但不是一般意义上的函数,闭包同时可以看做是一个对象。闭包中引用的外部变量,就是上面晦涩的闭包定义中所指的自由变量。
伟大的不知疲倦的布道者Martin Flower的解释
英文的:http: //martinfowler.com/bliki/Closure.html
中文的:http://blog.csdn.net/limux/archive/2005/07/05/413911.aspx
JAVA目前不支持闭包,我们看看几种动态语言中的闭包:
1、javascript中的闭包:
function a(){
var i=0;
function b(){
alert(++i);
}
return b;
}
var c = a();
c();
内部函数b()就是一个闭包。因为变量c对函数b()的引用,自由变量i在函数a()执行完之后不会被释放,从而可以保持自由变量的值。
其实javasript中的所有函数都可以理解成是闭包。
javascript闭包的延伸阅读
http://www.cn-cuckoo.com/2007/08/01/understand-javascript-closures-72.html
2、ruby中的闭包:
[‘lions’, ‘tigers’, ‘bears’].each {|item| puts item}
又如:
result = db.query “select * from words”;
result.each {|row| do_something_with_row}
3、groovy中的闭包:
def one = { num1, num2 ->;
println “param is: $num1 & $num2”;
}
one(2, 3) // 简便写法。输出 param is: 2 & 3
one 2, 3 // 省略()的等效写法
one.call(2, 3) // 使用call方法
one.call 2, 3 // 省略()等效写法
groovy闭包的延伸阅读
http://lggege.javaeye.com/blog/365242
4、python中的闭包:
def counter (st = 0)
count = [st]
def incr()
count[0] = 1
return count[0]
return incr
c = counter(5)
在JAVA中,可以通过内部类模拟闭包的行为:
JdbcTemplate template = new JdbcTemplate(dataSource);
final List names = new LinkedList();
template.query(“SELECT id,name FROM types ORDER BY name”,
new RowCallbackHandler() {
public void processRow(ResultSet rs)
throws SQLException
{
names.add(rs.getString(1));
}
});
那么,如果JAVA引入闭包支持,我们就可以这么写:
JdbcTemplate template = new JdbcTemplate(dataSource);
final List names = new LinkedList();
template.query(“SELECT id,name FROM types ORDER BY name”,
{
names.add(rs.getString(1));
}
);
是不是简洁很多?相信用Swing做桌面程序的童靴会有更大的感动。
闭包容易预见的好处是:
1、更简洁的代码;
2、更简练的模块:
3、更简明的抽象;