Java 8 Lambda变量范围

编码器

我有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.

唯一的区别是idxint或int数组。

根本原因是什么?

谢尔盖·卡里尼琴科(Sergey Kalinichenko)

根本原因是JVM缺乏构造对局部变量的引用的机制,这是idx++idx一个int或某些不可变类型(例如String需要执行的操作由于您尝试进行突变idx,因此仅获取其值是不够的。Java将需要捕获一个引用,然后通过它修改值。

使用数组时,Java没有此问题,因为数组是引用对象。Java可以捕获永不更改的数组引用,并使用该不变的引用来更改对象。数组本身提供了必要的间接级别,因为Java数组是可变的。

我尝试使idxstatic并将其移动到main方法之外,但效果很好。但为什么?

因为在这种情况下,lambda不需要捕获对原始类型的局部变量的引用。对静态变量的引用很容易获得,因此捕获它没有问题。

同样,如果您创建idx一个成员变量,并在实例方法中使用lambda ,则代码将起作用这将使lambda可以idx通过this对象修改字段,而该字段可以自由捕获。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章