数组作为局部变量-不遵循Lambda中的“确定分配”规则

时间:2019-02-12 11:29:33

标签: java lambda java-8

已经看到以下线程:

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

以上代码段均未给出编译错误,我是否缺少某些内容?

1 个答案:

答案 0 :(得分:3)

在第一种情况下,v是类型int的变量,此处v的值是2,并且是final变量。当您尝试分配5时,由于无法更改final变量值(按预期工作),它给出了错误。

是第二种情况,v不是int类型的变量,而是array。在Java中,数组是对象,因此这里的v是一个引用。通常,引用是指对象,并包含对象的地址。当您尝试在v[0] = 5处执行操作时,您将更改对象内部的值,而不是引用的值。如果您尝试执行v = new int[1]v={5},则会出现编译错误