Как параметры и аргументы интерпретируются между функциональным интерфейсом и функцией в контексте ссылки на метод - PullRequest
3 голосов
/ 09 июля 2019
interface MyFunc<T> {
  boolean func(T v1, T v2);
}

class Foo {
  private int value;

  Foo(int v) { value = v; }

  boolean isGreater(Foo obj) {   <-- (*)
    return value > obj.value;    <-- (**)    
  }
}

class Demo {
  static <T> int counter(T[] vals, MyFunc<T> f, T v) {
    int count = 0;

    for (int i = 0; i < vals.length; i++)
      if (f.func(vals[i], v)) 
        count++;

    return count;
  }

  public static void main (String [] args) {
    int count;

    Foo[] values = new Foo[10];

    for (int i = 0; i < values.length; i++)
      values[i] = new Foo(i);

    count = counter(values, Foo::isGreater, new Foo(5));

    System.out.println("values bigger " + count);
  }
}

В этом коде есть функция isGreater (*), которая считает количество значений, которые меньше переданного значения в качестве аргумента. Я путаюсь, как interface MyFunc<T> делает вывод, что этот оператор возврата (**), который сравнивает значение двух переменных экземпляра Foo, имеет 2 параметра. Чтобы было более понятно, как MyFunc<T> принимает (T v1, T v2) в качестве параметров, и это соответствует функции isGreater(Foo obj), которая принимает ссылку типа Foo в качестве аргумента.

1 Ответ

3 голосов
/ 09 июля 2019

Обратите внимание, что isGreater является методом экземпляр .Как бы вы назвали метод экземпляра Foo?Вам понадобится экземпляр из Foo, в дополнение ко всем параметрам, требуемым для метода.

В случае isGreater вам фактически понадобятся два экземпляра Fooчтобы вызвать его (даже если для него требуется только 1 Foo в качестве параметра):

foo1.isGreater(foo2)
^^^^           ^^^^

Также обратите внимание, что при использовании Foo::isGreater вы не предоставляете ему экземпляр Foo для вызова isGreater включено!Обычно это не будет работать с методом экземпляра, но разработчики языка Java увидели его и позволили это.

В любом случае вам нужен экземпляр Foo для вызова isGreater и другойэкземпляр для передачи в качестве параметра.Поэтому мы можем «переписать» isGreater как статический метод, подобный следующему:

public static boolean isGreater(Foo foo1, Foo foo2) {
    return foo1.isGreater(foo2);
}

Экземпляр, для которого вы вызываете isGreater, получил «повышение» в качестве параметра!На самом деле этого не происходит, но это все еще служит объяснением того, почему это вообще возможно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...