Java中的闭包 [英] Closures in Java
问题描述
此示例是JavaScript(我不知道JS)中闭包的模拟:
This example is a simulation of closures in JavaScript (I don't know JS):
public class Lambda {
public static void main(String[] args) {
Supplier generator = Lambda.generator();
System.out.println(generator.get());
System.out.println(generator.get());
System.out.println(generator.get());
}
static Supplier<Integer> generator() {
Integer arr[] = {0};
return () -> ++arr[0];
}
}
输出为1 23。
通常,局部方法变量的寿命受到方法执行时间的限制。但是在这种情况下,对 arr []
的引用存储在某个位置。那么它存储在哪里,又是什么呢?
The output is 1 2 3.
Usually the lifespan of local method variables is limited by the method execution time. But in this case the reference to arr[]
is stored somewhere. So where is it stored and what's under the hood?
推荐答案
Java语言规范(§15.27.4)说:
The Java Language Specification (§15.27.4) says:
lambda表达式的值是对具有以下属性的类的实例的引用:
The value of a lambda expression is a reference to an instance of a class with the following properties:
- 该类实现目标功能接口类型...
因此,lambda定义了一个类,就像一个匿名类声明会执行此操作,并且lambda表达式会导致对该类实例的引用。对 arr
的引用由属于该实例的综合 final
字段保存。
So the lambda defines a class, much like an anonymous class declaration does, and the lambda expression results in a reference to an instance of that class. The reference to arr
is held by a synthetic final
field belonging to that instance.
以下是在JShell REPL中使用反射的示例,以演示具有合成字段的lambda:
Here's an example using reflection in the JShell REPL, to demonstrate a lambda with a synthetic field:
> class A { static Runnable a(int x) { return () -> System.out.println(x); } }
| created class A
> Runnable r = A.a(5);
r ==> A$$Lambda$15/1476394199@31ef45e3
> import java.lang.reflect.Field;
> Field f = r.getClass().getDeclaredFields()[0];
f ==> private final int A$$Lambda$15/1476394199.arg$1
> f.setAccessible(true);
> f.get(r)
$6 ==> 5
这篇关于Java中的闭包的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!