Как может Java Predicate ‹T› разрешить использование метода без аргументов?

Из того, что я изучил, Predicate - это функциональный интерфейс с абстрактным методом boolean test(T var1);. Итак, если я использую ссылку на метод Java 8 и передаю ее функции getAllVegeterianDish(List<Dish> dish, Predicate<Dish> p, определенной в классе VegDish, почему бы не получить ошибку, если я вызываю ее с помощью getAllVegeterianDish(menu, Dish :: isVegeterian);, поскольку isVegeterian() действительно соответствует сигнатуре функции boolean test(T var1), и авторы специально упомянули об этом в book Сигнатура ссылки на метод должна соответствовать типу контекста (здесь контекст - это предикат, который имеет тест абстрактного метода, который принимает 1 аргумент).

Я взял следующий код из книги «Современная Java в действии» с небольшими изменениями.

package modernjavainaction.chap04;

import java.util.Arrays;
import java.util.List;

public class Dish {

  private final String name;
  private final boolean vegetarian;
  private final int calories;
  private final Type type;

  public Dish(String name, boolean vegetarian, int calories, Type type) {
    this.name = name;
    this.vegetarian = vegetarian;
    this.calories = calories;
    this.type = type;
  }

  public String getName() {
    return name;
  }

  public boolean isVegetarian() {
    return vegetarian;
  }

  public int getCalories() {
    return calories;
  }

  public Type getType() {
    return type;
  }

 

  public enum Type {
    MEAT,
    FISH,
    OTHER
  }

  @Override
  public String toString() {
    return name;
  }

  public static final List<Dish> menu = Arrays.asList(
      new Dish("pork", false, 800, Dish.Type.MEAT),
      new Dish("beef", false, 700, Dish.Type.MEAT),
      new Dish("chicken", false, 400, Dish.Type.MEAT),
      new Dish("french fries", true, 530, Dish.Type.OTHER),
      new Dish("rice", true, 350, Dish.Type.OTHER),
      new Dish("season fruit", true, 120, Dish.Type.OTHER),
      new Dish("pizza", true, 550, Dish.Type.OTHER),
      new Dish("prawns", false, 400, Dish.Type.FISH),
      new Dish("salmon", false, 450, Dish.Type.FISH)
  );

}
package modernjavainaction.chap04;

import static java.util.stream.Collectors.toList;
import static modernjavainaction.chap04.Dish.menu;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

public class VegDish {

  public static void main(String[] args) {
  
      List<Dish> res = getAllVegeterianDish(menu, Dish :: isVegeterian);
      System.out.println(res);
  }


  public static List<Dish> getAllVegeterianDish(List<Dish> dish, Predicate<Dish> p) {
      List<Dish> vegan = new ArrayList<>();
      for(Dish d : dish) {
          if(p.test(d)) {
              vegan.add(d);
          }
      }
      return vegan;
  }





Изменить: Итак, я понял, что в моем понимании есть пробел, и, чтобы сначала понять ссылку на метод, мы должны знать, что такое эквивалентная лямбда, а именно,

List<Dish> res = getAllVegeterianDish(menu, (Dish d) -> d.isVegeterian());

где d - произвольный объект из класса Veg. Теперь, если вы не знаете, что такое произвольный объект, прочтите различные типы ссылок на методы в документации оракула и проверьте там таблицу Виды ссылок на методы документы oracle для справки по методам. Позвольте мне рассказать вам, что я понимал под термином «произвольный». Это означает, что вы используете объект какого-то другого класса в текущем классе. Итак, в нашем примере лямбда мы используем объект d типа Dish в классе Veg.

Теперь правило преобразования лямбды в ссылку на метод такого типа:

            Lambda
            (args0) -> args0.instanceMethod()

            Method Reference
            ClassName :: instanceMethod

            where args0 is of type Class Name

Теперь, используя приведенный выше план, давайте заменим нашу лямбду ссылкой на метод args0 - ›d instanceMethod () -› isVegeterian ()

Таким образом, соответствующая ссылка на метод

List<Dish> res = getAllVegeterianDish(menu, Dish :: isVegeterian);

Приведенный выше план я получил из книги «Современная Java в действии».


person Niraj Chowdhary    schedule 24.05.2021    source источник
comment
@samabcde означает ли это, что когда я пишу p.test (d), это все равно что сказать d.isVegeterian ()? какая Java делает это за кулисами?   -  person Niraj Chowdhary    schedule 24.05.2021
comment
Что касается первого вопроса, ваше предположение верно. Что касается второго вопроса, я не знаю, как java реализует это за сценой, вы можете опубликовать другой вопрос.   -  person samabcde    schedule 25.05.2021
comment
@samabcde Спасибо за потенциальных клиентов, это было полезно   -  person Niraj Chowdhary    schedule 25.05.2021