我认为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表达式只保留对此实例的引用(final)。
在这种情况下,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.
所以你的问题的答案将是“是”。