-2
给了C#代码:比较拉姆达捕获C#和Java
int x = 10;
Func<int> next =() => { return ++x; };
Console.WriteLine("Before lambda, x = {0}", x);
Console.WriteLine("The successor of {0} is {1}", x, next());
Console.WriteLine("After lambda, x = {0} \n", x);
输出是:
Before lambda, x = 10
The successor of 10 is 11
After lambda, x = 11
拉姆达后,x的值是受拉姆达行动的话,这相当于通过引用将参数传递给函数。
让我们与Java比较:
interface Inc
{
int Increment();
}
int x = 10;
Inc next =() -> { return ++x; };
System.out.println("Before lambda, x = " + x);
System.out.println("The successor of " + x + " is " + next.Increment()); // ERROR: local variables referenced from a lambda expression must be final or effectively final
System.out.println("After lambda, x = " + x + "\n");
如果我改变拉姆达这样:
Inc next =() -> { return x+1; };
输出是:
Before lambda, x = 10
The successor of 10 is 11
After lambda, x = 10
拉姆达后,x的值不受lambda动作的影响,所以这相当于通过值将参数传递给函数。
阻止Java更改捕获的变量的技术原因是什么?
我知道错误消息说的话:
«从lambda表达式中引用的局部变量必须是最后的或有效的最后»
但这是不够的我。这背后的技术原因是什么?
如果Java允许捕获的变量可能被lambda更改,结果会是什么?
谢谢。
我认为这与副作用无关,因为变量是由值捕获的,所以在lambda里面我们有一个变量的副本。 –
@ArnbjorgJohansen准确地说,你有一个*副本*的变量,这意味着你不能更新原件。为了防止你错误地认为更新副本会更新原文,语言设计者做出了一个伟大的决定,要求变量被*(有效)* final(不可变),所以你不能*犯这个错误。 ---嗯......我想这就是答案*“这背后的技术原因是什么?”* – Andreas
@ArnbjorgJohansen状态的变化是一个副作用。 –