【发布时间】:2014-03-31 21:56:52
【问题描述】:
考虑以下几乎可编译的 Java 8 代码:
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;
}
}
你会注意到User user = users.stream().filter((user) -> user.getId() == 1).findAny().get(); 抛出编译器错误:
变量用户已在方法 main(String[]) 中定义
我的问题是:为什么 Lambda 表达式将初始化的变量与已经定义的 Lambda 表达式放在同一行?我了解 Lambda 在自身之外寻找(并使用)局部变量,因此您不能将在 Lambda 中使用的变量命名为与外部变量相同。但是为什么正在定义的变量被认为已经定义了?
【问题讨论】:
-
声明发生在初始化之前。您的局部变量
user在user之前定义在 lambda 表达式中。 -
@MirroredFate 我认为关键在于 lambda 表达式
user参数实际上应该在完全不同的上下文(表达式的评估上下文)中使用,那么它为什么会受到影响由外部定义的user变量? -
目前我能想到的唯一论据是变量
user是闭包环境的一部分,它已经在 lambda 表达式的上下文中,所以,如果你声明另一个变量user,存在名称冲突。但是,我仍然想知道,为什么它没有被简单地遮住。这可能与事物在引擎盖下的仪表化方式有关吗? -
@EdwinDalorzo 他的问题是为什么正在定义的变量被认为已经定义?,我的评论试图解释这一点。
-
您混淆了声明和初始化。变量在初始化之前声明。对于初始化程序中的 lambda,变量
user已声明,但尚未初始化。这对于没有 lambdas 的局部变量是一样的,例如对于int x=x+1;,第二个x将引用变量x,该变量已经声明,但引用无效,因为x那时还没有初始化 .不会尝试在外部范围内找到已初始化的x。