final
actually means that you must assign it once (and only once, as guaranteed by compile time analysis). For instance, the following code is invalid:
final String lastName;
List<Item> items = new ArrayList<Item>();
items.add(new Item("only one element"));
for (Item item:items) lastName = item.getName();
In your second lambda expression, the consumer assigns to lastName
, which has been declared as final
:
final String lastName;
items.forEach(item -> lastName = item.getName());
Since variables referenced in a lambda expression must be effectively final (i.e. such that the final
keyword may be added to its definition), deleting the final
keyword in the declaration of lastName
doesn't help: here lastName
is effectively final, and the consumer assigns to an effectively final variable.
String lastName;
items.forEach(item -> lastName = item.getName());
On the other hand, in your first expression the effectively final variable is lastName
, which is an array. Then you can do:
String[] lastName = {""};
items.forEach(item -> lastName[0] = item.getName());
Because here you are not assigning to the effectively final variable, but only modifying its elements (remember that what is constant is the reference, not its values), as it is also the case in the following example:
final String[] lastName = new String[1];
lastName[0]="foo";