为什么实例方法的Java方法引用无法分配给Consumer接口

Sha*_*yan 5 java lambda

这是我的代码:

public class SearchByLambda {

     private Map<String,Consumer<Person>> searchCritertiaHolder = new HashMap<String,Consumer<Person>>();

     private static final String AGED = "aged";

     public SearchByLambda(){
           searchCritertiaHolder.put(AGED, (Person p)-> {p.filterAgedPerson(p);} );
     }

     private Consumer<Person> getFilter(String personType){
          return searchCritertiaHolder.get(personType);
     }

     public static void main(String[] args) {
          SearchByLambda searchUsage = new SearchByLambda();
          Person p = new Person(59,"shailesh");
          Person p1 = new Person(58,"ganesh");

          searchUsage.getFilter(AGED).accept(p);
          searchUsage.getFilter(AGED).accept(p1);

          Person.printAgedPersons();
     }
 }

 class Person{

       private static List<Person> agedPersons = new ArrayList<>();

       private int age;

       private String name;

       public int getAge() {
              return age;
       }

       public void setAge(int age) {
          this.age = age;
       }

       public String getName() {
            return name;
       }

       public void setName(String name) {
            this.name = name;
       }

       public Person(int age,String name){
           this.age = age;
           this.name = name;
       }

       public void filterAgedPerson(Person person){
          if(person.getAge() > 58){
              agedPersons.add(person);
          }
       }

       public static void printAgedPersons(){
            for(Person person : agedPersons){
                System.out.println(person.getName());
            }
       }
 }
Run Code Online (Sandbox Code Playgroud)

当我替换以下Lambda表达式时

     searchCritertiaHolder.put(AGED, (Person p)-> {p.filterAgedPerson(p);});
Run Code Online (Sandbox Code Playgroud)

              searchCritertiaHolder.put(AGED, Person::filterAgedPerson);
Run Code Online (Sandbox Code Playgroud)

它给了我编译错误.我正在使用java 8并通过eclipse进行编译.为什么会这样?为什么我不能将任意对象的实例方法的方法引用分配给消费者功能接口?

msa*_*ord 6

您的定义filterAgedPerson将a Person作为参数,即使它不是静态方法.它不需要,如果你想用它作为一个它不应该Consumer<Person>.你最终得到的是兼容的东西BiConsumer<Person, Person>.

以这种方式思考它可能会有所帮助:对非静态方法的方法引用始终采用"额外"参数,该参数用作this.

使用当前代码结构修复此问题的最简单方法是修改filterAgedPerson方法,使其不Person作为参数

   public void filterAgedPerson() {
      if (this.getAge() > 58) {
          agedPersons.add(person);
      }
   }
Run Code Online (Sandbox Code Playgroud)

另外,您可能还需要考虑使用过滤器Predicate<Person>而不是Consumer<Person>将结果处理移动到其他位置.随着事情变得更加复杂,这将为您提供更大的灵活性.