我有2个代码示例:
int[] idx = { 0 };
List<String> list = new ArrayList<String>();
list.add("abc");
list.add("def");
list.add("ghi");
list.stream().forEach(item -> {
System.out.println(idx[0] + ": " + item);
idx[0]++;
});
好好工作。
虽然此代码具有编译错误:
int idx = 0;
List<String> list = new ArrayList<String>();
list.add("abc");
list.add("def");
list.add("ghi");
list.stream().forEach(item -> {
System.out.println(idx + ": " + item);
idx++;
});
说:
Local variable idx defined in an enclosing scope must be final or effectively final.
唯一的区别是idx
int或int数组。
根本原因是什么?
根本原因是JVM缺乏构造对局部变量的引用的机制,这是idx++
在idx
一个int
或某些不可变类型(例如String
)时需要执行的操作。由于您尝试进行突变idx
,因此仅获取其值是不够的。Java将需要捕获一个引用,然后通过它修改值。
使用数组时,Java没有此问题,因为数组是引用对象。Java可以捕获永不更改的数组引用,并使用该不变的引用来更改对象。数组本身提供了必要的间接级别,因为Java数组是可变的。
我尝试使
idx
static并将其移动到main方法之外,但效果很好。但为什么?
因为在这种情况下,lambda不需要捕获对原始类型的局部变量的引用。对静态变量的引用很容易获得,因此捕获它没有问题。
同样,如果您创建idx
一个成员变量,并在实例方法中使用lambda ,则代码将起作用。这将使lambda可以idx
通过this
对象修改字段,而该字段可以自由捕获。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句