我开始了解lambda语法,并且发现了一些让我感到烦恼的事情:
private ArrayList<Person> list = new ArrayList<>();
public void remove(Person person){
this.list.remove(person);
}
public void run(){
list.stream().filter(p -> p.getAge() > 15).forEach(p -> p.setAge(p.getAge() + 1));
list.stream().filter(p -> p.getAge() > 15).forEach(PersonDatabase::remove);; //Syntax error
}
当我尝试使用最后一行代码删除对象时,我收到一条错误消息,指出该方法不是静态的。为什么我不能参考我已经上过的课程,但是当我使用Person::getName
时,它也不是静态的,它可以正常工作吗?
答案 0 :(得分:4)
为什么我不能参考我已经上过的课程?
如果remove
是非静态的,则需要一个接收者(一个对象来调用该方法)。
如果此代码位于PersonDatabase
内,则应使用以下语法:this::remove
。
但是当我使用
Person::getName
时,它也不是静态的,它可以正常工作吗?
这是因为p -> p.getName()
(几乎)等同于Person::getName
。自动选择参数p
作为Person::getName
调用的接收者。
换句话说,这两个变种
/* Static Person method */ static void method(Person p) { ... }
和这个变种
/* Non-static Person method */ void method() { ... }
迭代Person::method
个对象时,可用作Person
。在前一种情况下,p
将作为参数传递,在后一种情况下,p
将用作接收者。
答案 1 :(得分:0)
PersonDatabase::remove
有两个参数 - 一个是隐式的 - 当前的PersonDatabase
实例,另一个是显式的 - 传递的Person
实例。
因此,只有单个Person
实例可用时,才能使用此方法引用。当您将remove方法更改为静态时,可以消除隐式PersonDatabase
参数,只留下一个Person
参数,这会使您的方法与forEach
所需的参数匹配。 / p>