我刚刚看到this question,显然很明显Java应该拒绝访问lambda表达式体内的非final变量。为什么呢?
编辑:例如,我不明白为什么以下代码有害:
String[] numbers = new String[10]; // put some numerical strings in
BigInteger sum = new BigInteger("0");
numbers.forEach(n -> sum = sum.add(new BigInteger(n)));
答案 0 :(得分:5)
Lambdas只是语法糖,它们被编译成anonymous inner classes
。匿名内部类因其范围而无法使用non-final
局部变量。这是解释:
方法的局部变量存在于堆栈中,并且仅存在 在该方法的生命周期。你已经知道了一个范围 局部变量仅限于声明变量的方法。 当方法结束时,堆栈框架被吹走并变量 是历史。但即使在方法完成后,内部类也是如此 如果,for,在其中创建的对象可能仍然在堆上存活 例如,对它的引用被传递到其他一些代码然后 存储在实例变量中。因为局部变量不是 只要方法本地内部类对象保证是活着的, 内部类对象不能使用它们。除非局部变量是 标记为最终!
礼貌:SCJP 6 Kathy Sierra和Bert Bates的学习指南
答案 1 :(得分:0)
我不确定这是否是答案,但在Java的文档中,它说明了以下内容:
对有效最终变量的限制禁止访问动态变化的局部变量,其捕获可能会引入并发问题。与最终限制相比,它减少了程序员的文书负担。
我从中理解的是,当您将lambda表达式传递给方法时,该表达式不应导致并发问题,因为此方法可以由多个线程同时使用,并且使用非最终变量可能会导致竞争条件
文档页面,如果您想自己阅读并获得更多信息:http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.27.2