2016-11-17 2 views
2

Для java8 в примере действия :: https://github.com/java8/Java8InAction/blob/master/src/main/java/lambdasinaction/chap1/FilteringApples.javajava8 предикатном с параметром

public static boolean isGreenApple(Apple apple), 
public static boolean isHeavyApple(Apple apple) { 

Я хочу, чтобы добавить подобный метод, например

public static boolean isAppleOfColor(Apple apple, String color) 

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

List<Apple> colorApples = filterApples(inventory, FilteringApples::isAppleOfColor("red")); 

Но я не могу передать аргументы в FilteringApples :: isAppleOfColor ("красный").

До сих пор я достиг этого, используя следующие:

public static Predicate<Apple> colourMatches(String color) { 
    return p->color.equals(p.getColor()); 
} 

и затем вызвать

List<Apple> colorApples = filterApples(inventory, (Apple a)->a.colourMatchesOnApple("red")); 
    System.out.println(colorApples); 

Это работает. Но есть способ, которым я могу использовать "называют" параметризованные методы, такие как FilteringApples::isAppleOfColor("red").

благодаря

EDIT

Спасибо Все, я только что понял, в JLS 15.13: https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.13 как следующий текст:

Невозможно указать конкретную подпись, которая должна быть сопоставлена, например, , Массивы :: sort (int []). Вместо этого функциональный интерфейс предоставляет типы аргументов, которые используются в качестве входных данных для алгоритма разрешения перегрузки (§15.12.2). Это должно удовлетворять подавляющее большинство случаев использования ; когда возникает редкая потребность в более точном контроле, можно использовать выражение лямбда .

ответ

4

Ссылка на метод не может захватывать дополнительные переменные.

Что вы можете сделать, это

List<Apple> colorApples = filterApples(inventory, a -> isAppleOfColor(a, "red")); 

который вы отметите короче.

Примечание: я бы избегал использования метода esc, когда первый аргумент является типом, который вы пишете. Гораздо лучше добавить

// added to Apple 
public boolean isColor(String color) 

и вы можете вызвать

List<Apple> colorApples = filterApples(inventory, a -> a.isColor("red")); 

, который, вероятно, будет таким же, как

List<Apple> colorApples = inventory.stream() 
            .filter(a -> a.isColor("red")) 
            .collect(toList()); 
+1

Да спасибо, добавив его в яблоко, также работает и в том случае, нам даже не нужен метод для статичности. Мне было интересно узнать о методе, в котором вы пояснили, что он не может захватывать дополнительные переменные. Я пробовал проверять JLS и как-то пропустил его. Будет здорово, если у вас есть секция JLS, удобная для моего понимания. – Optional

+1

@Optional note: ссылки на методы могут захватывать значение слева от '::'. например 'Потребитель out = System.out :: println;' captures 'System.out' –

+4

Обратите внимание, что в этом конкретном примере в качестве аргумента метода предоставляется только постоянное значение, но никакая переменная не записывается. Это все еще не поддерживается ссылками на методы, поэтому требуется выражение лямбда, но выражение лямбда * не захватывает *, что может иметь преимущество в производительности за захват лямбда. – Holger

Смежные вопросы