说在前面:在计算机科学中,闭包是指一个函数以及其引用的周围环境(变量)所组成的整体。简单来说,闭包允许一个函数访问并操作其外部函数作用域中的变量,即使外部函数已经执行完毕。
Java函数式编程—闭包(Closure)
何为闭包,闭包就是函数对象与外界变量绑定在一起,形成的整体。例如在Java中使用函数式编程实现一个闭包:
public class ClosureTest {
interface Lambda {
int add(int y);
}
public static void main(String[] args) {
int x = 10;
highOrder(y -> x + y);
}
static void highOrder(Lambda lambda) {
System.out.println(lambda.add(20));
}
}
- 代码中的 y -> x + y 和 x = 10,就形成了一个闭包
- 可以想象成,函数对象有个背包,背包里可以装变量随身携带,将来函数对象甭管传递到多远的地方,包里总装着个 x = 10
- 有个限制,局部变量 x 必须是 final 或 effective final 的,effective final 意思就是,虽然没有用 final 修饰,但就像是用 final 修饰了一样,不能重新赋值,否则就语法错误。
- 意味着闭包变量,在装进包里的那一刻,就不能变化了
- 道理也简单,为了保证函数的不变性,防止破坏成道
- 闭包是一种给函数执行提供数据的手段,函数执行既可以使用函数入参,还可以使用闭包变量
例:
public class ClosureTest {
// 闭包作用:给函数对象提供参数以外的数据
public static void main(String[] args) throws IOException {
// 创建 10 个任务对象,并且每个任务对象给一个任务编号
List<Runnable> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
int k = i + 1;
Runnable task
= () -> System.out.println(Thread.currentThread()+":执行任务" + k);
list.add(task);
}
ExecutorService service = Executors.newVirtualThreadPerTaskExecutor();
for (Runnable task : list) {
service.submit(task);
}
System.in.read();
}
}
Python闭包
在 Python 中,闭包是一个比较重要且有趣的概念。
当一个嵌套函数(函数里面的函数)引用了其外部函数的变量,并且外部函数返回了这个嵌套函数时,就形成了一个闭包。
简单来说,闭包使得函数能够记住并访问其定义时所在的环境(包括变量),即使外部函数已经执行完毕。
以下是一个简单的闭包示例:
def outer_function(x):
def inner_function(y):
return x + y
return inner_function
closure = outer_function(10)
print(closure(5))
在上述示例中,inner_function
就是一个闭包。它引用了外部函数 outer_function
的变量 x
。即使 outer_function
执行结束,inner_function
仍然能够记住并使用 x
的值。
闭包的主要优点包括:
实现数据隐藏和封装:外部无法直接访问闭包内引用的变量,增强了代码的安全性和封装性。
保存函数的状态:可以利用闭包来保存函数在不同调用之间的中间状态。
实现函数工厂:通过闭包可以创建一系列具有相似行为但又有细微差别的函数。
需要注意的是,在使用闭包时,如果对引用的外部变量进行修改,需要使用 nonlocal
关键字明确声明,否则会导致意外的结果。
闭包的缺点:
- 内存管理:由于闭包会保留对外部函数变量的引用,可能会导致内存泄漏问题。如果闭包被长时间引用而不释放,可能会占用大量内存。
- 变量作用域:在使用闭包时,要注意变量的作用域,避免意外的变量覆盖和冲突。