Java中的闭包与回调
闭包是可以包含自由 (未绑定) 变量的代码块; 这些变量不是在这个代码块
或者任何全局上下文中定义的,而是在定义代码块的环境中定义。 “闭包”一词
来源于以下两者的结合: 要执行的代码块 (由于自由变量的存在, 相关变量引用
没有释放)和为自由变量提供绑定的计算环境(作用域) 。在 Scheme、Common
Lisp、Smalltalk、Groovy、JavaScript、Ruby 和 Python 等语言中都能找到对闭包
不同程度的支持。
闭包的价值在于可以作为函数对象或者匿名函数, 对于类型系统而言这就意
味着不仅要表示数据还要表示代码。 支持闭包的多数语言都将函数作为第一级对
象,就是说这些函数可以存储到变量中、 作为参数传递给其他函数, 最重要的是
能够被函数动态地创建和返回。
首先让我们先来看一下在 Javascript中闭包 (Closure)
function a(){
var i=0;
function b(){
alert(++i);
}
return b;
}
var c = a();
c();
这段代码有两个特点:
1、函数 b 嵌套在函数 a 内部;
2、函数 a 返回函数 b。
这样在执行完 var c=a()后,变量 c 实际上是指向了函数 b,再执行 c()后就会
弹出一个窗口显示 i 的值(第一次为 1)。这段代码其实就创建了一个闭包, 为什么?
因为函数 a 外的变量 c 引用了函数 a 内的函数 b,就是说:
当函数 a 的内部函数 b 被函数 a 外的一个变量引用的时候, 就创建了一个闭
包。
简而言之,闭包的作用就是在 a 执行完并返回后,闭包使得 Javascript的垃
圾回收机制 GC不会收回 a 所占用的资源,因为 a 的内部函数 b 的执行需要依赖
a 中的变量。
在上面的例子中,由于闭包的存在使得函数 a 返回后, a 中的 i 始终存在,
这样每次执行 c(),i 都是自加 1 后 alert 出 i 的值。
那么我们来想象另一种情况, 如果 a 返回的不是函数 b,情况就完全不同了。
因为 a 执行完后, b 没有被返回给 a 的外界,只是被 a 所引用,而此时 a 也只会
被 b 引用,因此函数 a 和 b 互相引用但又不被外界打扰 (被外界引用 ),函数 a 和
b 就会被 GC回收。
闭包的应用场景
1、保护函数内的变量安全。以最开始的例子为例,函数 a 中 i 只有函数 b
才能访问,而无法通过其他途径访问到,因此保护了 i 的安全性。
2、在内存中维持一个变量。依然如前例,由于闭包,函数 a 中 i 的一直存
在于内存中,因此每次执行 c(),都会给 i 自加 1。