Consider the following almost compilable Java 8 code:
public static void main(String[] args) {
LinkedList users = null;
users.a
The question is pretty old, but i thought my answer can add better clarity to the already given answers. Particularly to that of @Sotirios Delimanolis . The lambda assignment in
User user = users.stream().filter((user) -> user.getId() == 1).findAny().get();
fails for the same reason the following code fails.
Object e = null;
try{
throw new Exception();
} catch(Exception e) { // compilation fails because of duplicate declaration
//do nothing
}
A local variable (§14.4), formal parameter (§8.4.1, §15.27.1), exception parameter (§14.20), and local class (§14.3) can only be referred to using a simple name, not a qualified name (§6.2).
Some declarations are not permitted within the scope of a local variable, formal parameter, exception parameter, or local class declaration because it would be impossible to distinguish between the declared entities using only simple names.
Because lambdas have the same scope of all the things mentioned above, this fails.
Note, this limitation is going to be removed in the future releases. Quote from JEP-302:
Lambda parameters are not allowed to shadow variables in the enclosing scopes. (In other words, a lambda behaves like a for statement - see JLS) This often causes problems, as in the following (very common) case:
Map<String, Integer> msi = ...
...
String key = computeSomeKey();
msi.computeIfAbsent(key, key -> key.length()) //error
Here, the attempt to reuse the name key as a lambda parameter in the computeIfAbsent call fails, as a variable with the same name was already defined in the enclosing context.
It would be desirable to lift this restriction, and allow lambda parameters (and locals declared with a lambda) to shadow variables defined in enclosing scopes. (One possible argument against is readability: if lambda parameters are allowed to shadow, then in the above example, the identifier 'key' means two different things in the two places where it is used, and there seem to be no syntactic barrier to separate the two usages.)
look at the code
User user = users.stream().filter((user) -> user.getId() == 1).findAny().get();
The variable name is user
and the variable inside the lambda is also user
try changing it to be something like this
User user = users.stream().filter((otherUser) -> otherUser.getId() == 1).findAny().get();
Let's go to the Java Language Specification on names and their scopes
The scope of a formal parameter of a method (§8.4.1), constructor (§8.8.1), or lambda expression (§15.27) is the entire body of the method, constructor, or lambda expression.
The scope of a local variable declaration in a block (§14.4) is the rest of the block in which the declaration appears, starting with its own initializer and including any further declarators to the right in the local variable declaration statement.
Then, on the subject of shadowing and obscuring
A local variable (§14.4), formal parameter (§8.4.1, §15.27.1), exception parameter (§14.20), and local class (§14.3) can only be referred to using a simple name, not a qualified name (§6.2).
Some declarations are not permitted within the scope of a local variable, formal parameter, exception parameter, or local class declaration because it would be impossible to distinguish between the declared entities using only simple names.
It is a compile-time error if the name of a local variable v is used to declare a new variable within the scope of v, unless the new variable is declared within a class whose declaration is within the scope of v.
So, in
User user = users.stream().filter((user) -> user.getId() == 1).findAny().get();
, the scope of the variable user
is everything after it in that block. Now you are trying to use the name of that variable to declare a new variable within the scope, but not
within a class whose declaration is within the scope of v.
so a compile time error occurs. (It's declared in a lambda expression, not in a class.)
It is the same as with any other local variables: you're not allowed to shadow them in more inner {} blocks.