Вызов метода для объекта Lambda возвращает значение - PullRequest
3 голосов
/ 23 сентября 2019

выражение this.apply(stringValue) возвращает true для лямбда-выражения j8Test.PerformChange$$Lambda$2/284720968@2f4d3709

Почему оно возвращает true, а не false.И почему это вообще что-то возвращает?(Я не говорю обо всех других объектах типа PerformChangeImpl)

private final List<PerformChange> performChangeList = Arrays.asList(
        new PerformChangeImpl("1"),
        new PerformChangeImpl("2"),
        new PerformChangeImpl("3")
);

@FunctionalInterface
interface PerformChange extends Function<String, Boolean> {

    default PerformChange performChange(PerformChange input) {
        System.out.println("1 this: " + this);
        System.out.println("2 input: " + input);
        return stringValue -> {
            System.out.println("\n3 this: " + this);
            System.out.println("4 input: " + input);
            if (this.apply(stringValue)) {
                System.out.println("5 this: " + this);
                return input.apply(stringValue);
            }
            return false;
        };
    }
}

class PerformChangeImpl implements PerformChange {

    private final String value;

    public PerformChangeImpl(String value) {
        this.value = value;
    }

    @Override
    public Boolean apply(String string) {
        System.out.println("\n6: " + this);
        System.out.println("7: " + string);
        return true;
    }

    @Override
    public String toString() {
        return "obj id: " + value;
    }
}

и

private void executePerformChanges() {
    System.out.println(performChangeList.stream()
            .reduce(PerformChange::performChange)
            .orElse(new PerformChangeImpl("4"))
            .apply("test"));
}

результат в

1 this: obj id: 1
2 input: obj id: 2
1 this: j8Test.PerformChange$$Lambda$2/284720968@2f4d3709
2 input: obj id: 3

3 this: j8Test.PerformChange$$Lambda$2/284720968@2f4d3709
4 input: obj id: 3

3 this: obj id: 1
4 input: obj id: 2

6: obj id: 1
7: test
5 this: obj id: 1

6: obj id: 2
7: test
5 this: j8Test.PerformChange$$Lambda$2/284720968@2f4d3709

6: obj id: 3
7: test
true

Process finished with exit code 0

Ответы [ 2 ]

4 голосов
/ 23 сентября 2019

Здесь:

public Boolean apply(String string) {
  ...

Ваш класс PerformChangeImpl переопределяет метод apply().Это ядро ​​интерфейса Function.

И, наконец, ваш код вызывает:

.apply("test"))

И самое последнее утверждение в apply():

return true;

Метод возвращает trueпотому что ты сказал это сделать.Таким образом, вы должны либо изменить тело этого метода, чтобы оно возвращало true / false на основе какого-либо условия, либо вам не следует вызывать apply() в конце.

И обратите внимание: это становится действительно очевидным из печатных заявлений.В итоге вы получаете 6 и 7, которые вы печатаете в apply() класса PerformChangeImpl.

Также обратите внимание: ваш по умолчанию метод выполняет:

if(this.apply(stringValue)) { 

Это вызывает apply() для "окружающих" PerformChangeImpl ... и возвращает true.

2 голосов
/ 23 сентября 2019

У вас есть две реализации PerformChange:

  1. Класс PerformChangeImpl, который функциональный метод apply всегда возвращает true.Нет никакого шанса получить false.
  2. Лямбда-выражение str -> apply(str) && input.apply(str), которое вы генерируете в performChange (я немного упростил его).Существует шанс получить false, если apply(str) или input.apply(str) вернет false.

Поскольку performChangeList содержит только PerformChangeImpl экземпляров, сгенерированная лямбда может быть упрощена доinput.apply(str), Другими словами, метод будет выглядеть так:

default PerformChange performChange(PerformChange input) {
    // str -> apply(str) && input.apply(str)
    // str -> true && input.apply(str)
    // str -> input.apply(str)
    // input::apply
    // input
    return input;
}

, и результирующий true ожидается для любого заданного String, если performChangeList заполнен исключительно объектами PerformChangeImpl.

В качестве примечания, Function<String, Boolean> - это просто Predicate<String>, и лучше использовать последнее.

@FunctionalInterface
interface PerformChange extends Predicate<String> { ... }

class PerformChangeImpl implements PerformChange {
    @Override
    public boolean test(String string) { ... }
}
...