我认为final
限制有技术原因。lambda 表达式只是从周围的方法上下文中获取值,因为引用存在于堆栈中,并且不会在方法完成后继续存在。
如果将上下文的值放入引用中,则可以构建一个“真正的”闭包:
import java.util.function.Supplier;
public class CreatingAClosure {
public static void main(String[] args) {
Supplier<Supplier<String>> mutterfunktion = () -> {
int container[] = {0};
return () -> {
container[0]++;
return "Ich esse " + container[0] + " Kuchen.";
};
};
Supplier<String> essen = mutterfunktion.get();
System.out.println(essen.get());
System.out.println(essen.get());
System.out.println(essen.get());
}
}
奥斯加贝:
Ich esse 1 Kuchen.
Ich esse 2 Kuchen.
Ich esse 3 Kuchen.
您可以使用任何对象的任何合适实例代替数组,因为它位于堆上,并且只有对该实例的引用(最终)保留在 lambda 表达式中。
在这种情况下, 的值container
包含在mutterfunktion
中。每次调用mutterfunktion
都会创建一个新的引用实例。
无法从函数外部访问该值(在 Java 7 及之前的版本中很难构建)。由于 lambda 表达式是作为方法引用实现的,因此此示例中不涉及内部类。
您还可以container
在方法的上下文中定义您将能够在 lambda 之外进行更改:
public static void main(String[] args) {
int container[] = {0};
Supplier<String> essen = () -> {
container[0]++;
return "Ich esse " + container[0] + " Kuchen.";
};
System.out.println(essen.get());
System.out.println(essen.get());
container[0]++;
System.out.println(essen.get());
}
奥斯加贝:
Ich esse 1 Kuchen.
Ich esse 2 Kuchen.
Ich esse 4 Kuchen.
因此,您的问题的答案将是“是”。