【发布时间】:2019-06-14 17:28:37
【问题描述】:
我知道这个主题有很多问题,即使是very recent one,但我仍然无法解决一件事。考虑以下功能界面:
@FunctionalInterface
interface PersonInterface {
String getName();
}
还有这个实现:
class Person implements PersonInterface {
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
如果我查看这些线程 1 和 2,我希望以下代码输出 "Bob" 而不会抛出 NullPointerException,因为据我所知,当我创建供应商时,它会捕获Person 实例。
Person p = new Person("Bob");
Supplier<String> f = p::getName;
p = null;
System.out.println(f.get());
它正确输出"Bob"
现在我不明白的是为什么下面的代码也不输出"Bob"?
Person p = new Person("Bob");
Supplier<String> f = p::getName;
p.setName("Alice");
System.out.println(f.get());
它实际上输出"Alice"
在我看来,在第一个示例中,lambda 在创建 Person 对象时捕获了它的状态,并且在调用它时不会尝试重新评估它,而在第二种情况下,它似乎确实如此不捕获它,而是在调用它时重新评估它。
编辑 在重新阅读了其他线程和 Eran 的回答之后,我用 2 个指向同一个实例的人写了那个位:
Person p1 = new Person("Bob");
Person p2 = p1;
Supplier<String> f1 = p1::getName;
Supplier<String> f2 = p2::getName;
p1 = null;
p2.setName("Alice");
System.out.println(f1.get());
System.out.println(f2.get());
现在我可以看到它们都输出"Alice",即使 p1 为空,因此方法引用捕获了实例本身,而不是我错误假设的状态。
【问题讨论】:
-
我认为如果您更改了人名(如在您的代码块中)并且没有取回更新后的值,那会很奇怪/容易出错
标签: java java-8 instance functional-interface supplier