已经看到以下线程:
Java8 Stream compiler message -- local variable must be final or effectively final
Variable assignment in lambda expression
根据JavaDoc
使用了任何局部变量,形式参数或异常参数,但 未在Lambda表达式中声明的声明必须声明为final或 有效地最终确定(第4.12.4节),或者在以下情况下发生编译时错误: 尝试使用。
使用但未在lambda主体中声明的任何局部变量必须为 在lambda之前明确分配(第16节(确定分配)) 正文,否则会发生编译时错误。
关于变量使用的类似规则适用于内部类的主体 (第8.1.3节)。对有效最终变量的限制禁止 访问动态变化的局部变量,其捕获将 可能会引入并发问题。与最终相比 限制,它减轻了程序员的文书负担。
arrays
是规则 1 的例外吗?
验证Javadoc的示例程序:
List<Integer> li = Arrays.asList(1,2,3,45,678);
final int v = 2;
li.stream().filter(e-> e!=v).map(e->e).forEach(System.out::println);
v= 5;
第 v = 5; 行的编译错误,显然
违反最终分配规则的示例代码段
List<Integer> li = Arrays.asList(1,2,3,45,678);
final int[] v = {2};
li.stream().filter(e-> e!=v[0]).map(e->e).forEach(System.out::println);
v[0]= 5;
输出:
3
45
678
以上代码段均未给出编译错误,我是否缺少某些内容?
答案 0 :(得分:3)
在第一种情况下,v
是类型int
的变量,此处v
的值是2,并且是final
变量。当您尝试分配5时,由于无法更改final
变量值(按预期工作),它给出了错误。
是第二种情况,v
不是int
类型的变量,而是array
。在Java中,数组是对象,因此这里的v
是一个引用。通常,引用是指对象,并包含对象的地址。当您尝试在v[0] = 5
处执行操作时,您将更改对象内部的值,而不是引用的值。如果您尝试执行v = new int[1]
或v={5}
,则会出现编译错误