为什么lambda强迫我使用单个元素数组而不是最终对象?
我有以下课程:
public class Item{ private String name; //setter getter }
和物品的集合。 我想得到Collection中最后一项的名字。 要做到这一点,我只需迭代所有集合并使用最后。 问题是我不知道为什么它迫使我使用一个元素String数组。
为什么我必须使用:
String[] lastName = {""}; items.forEach(item -> lastName[0] = item.getName()); System.out.println(lastname[0]);
代替:
final String lastName; items.forEach(item -> lastName = item.getName()); System.out.println(lastname);
你不能将lastName
String
,因为在lambda(或匿名内部类)中使用的局部变量必须(有效)为final
( 参见此处 ),即你不能在.forEach
中每次执行lambda时覆盖它循环。 使用数组(或其他一些包装器对象)时,不要为该变量赋值,而只是更改它的某些方面,因此它可以是最终的。
或者,您可以使用reduce
跳到最后一项:
String lastName = items.stream().reduce((a, b) -> b).get().getName();
或者,如评论中所述, skip
前n-1个元素并在此之后取第一个元素:
String last = items.stream().skip(items.size() - 1).findFirst().get().getName();
final
实际上意味着你必须分配一次(并且只有一次,由编译时分析保证)。 例如,以下代码无效:
final String lastName; List- items = new ArrayList
- (); items.add(new Item("only one element")); for (Item item:items) lastName = item.getName();
在您的第二个lambda表达式中,使用者分配给lastName
,该lastName
已声明为final
:
final String lastName; items.forEach(item -> lastName = item.getName());
因为lambda表达式中引用的变量必须是有效的final (即final
关键字可以添加到其定义中),所以删除lastName
声明中的final
关键字没有帮助:这里lastName
实际上是final,并且消费者指定到一个有效的最终变量。
String lastName; items.forEach(item -> lastName = item.getName());
另一方面,在你的第一个表达式中, 有效的final变量是lastName
,它是一个数组。 然后你可以这样做:
String[] lastName = {""}; items.forEach(item -> lastName[0] = item.getName());
因为在这里你没有分配有效的最终变量,只是修改它的元素(记住什么是常量是引用,而不是它的值),因为在下面的例子中也是如此:
final String[] lastName = new String[1]; lastName[0]="foo";