Categories
discuss

Variable is already defined in method lambda

Consider the following almost compilable Java 8 code: public static void main(String[] args) { LinkedList users = null; users.add(new User(1, “User1”)); users.add(new User(2, …

Consider the following almost compilable Java 8 code:

public static void main(String[] args) {

    LinkedList<User> users = null;
    users.add(new User(1, "User1"));
    users.add(new User(2, "User2"));
    users.add(new User(3, "User3"));

    User user = users.stream().filter((user) -> user.getId() == 1).findAny().get();
}

static class User {

    int id;
    String username;

    public User() {
    }

    public User(int id, String username) {
        this.id = id;
        this.username = username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public int getId() {
        return id;
    }
}

You’ll notice User user = users.stream().filter((user) -> user.getId() == 1).findAny().get(); throws a compiler error:

variable user is already defined in method main(String[])

My question is: Why do Lambda expressions consider the variable that is being initialized on the same line as the Lambda expression as already defined? I understand Lambdas look outside themselves for (and use) local variables, so you can’t name the variables you use inside the Lambda the same as an outside variable. But why is the variable that is being defined considered already defined?

Answer

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.)

Source: stackoverflow
Text is available under the Creative Commons Attribution-ShareAlike License; additional terms may apply. By using this site, you agree to the Privacy Policy, and Copyright Policy. Content is available under CC BY-SA 3.0 unless otherwise noted. The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 © No Copyrights, All Questions are retrived from public domain..