Java 8 - явное несоответствие между анонимными классами и лямбда-функциями - PullRequest
0 голосов
/ 25 февраля 2019

, исследуя функциональное программирование на Java 8, я обнаружил следующее явное несоответствие.Приведенные ниже две конструкции должны быть эквивалентны:

  public static BiFunction<Integer, Integer, Integer> addTwoIntegers (Integer i1, Integer i2)
  {
    return new BiFunction<Integer, Integer, Integer>()
    {
      @Override
      public Integer apply(Integer i1, Integer i2)
      {
        return i1 +i2;
      }
    };
  }

  public static BiFunction<Integer, Integer, Integer> addTwoIntegers2 (Integer i1, Integer i2)
  {
    return (i1x, i2x) -> i1 + i2;
  }

Первое объявление - это традиционный анонимный класс, а второе - лямбда-функция, но в противном случае они должны быть эквивалентными.Теперь, вызывая их следующим образом:

    System.out.println("addTwoIntegers: " + addTwoIntegers(new Integer(0), new Integer(0)).apply(new Integer(5), new Integer(7)));
    System.out.println("addTwoIntegers2: " + addTwoIntegers2(new Integer(0), new Integer(0)).apply(new Integer(5), new Integer(7)));

Я получаю:

addTwoIntegers: 12
addTwoIntegers2: 0

Так что либо эти два объявления не эквивалентны, что трудно признать, либо, если они эквивалентныпри условии, что они вызываются в одном контексте с одинаковыми параметрами, они должны давать одинаковый результат.Разве это не противоречие?
Огромное спасибо заранее тому, кто сможет затенить здесь немного света.
С уважением, Николас

Ответы [ 2 ]

0 голосов
/ 25 февраля 2019

То есть оба объявления не эквивалентны, что трудно признать,

Они действительно не эквивалентны!

Аргументы метода для addTwoIntegersто есть i1 и i2 не используются в вашем первом примере.

public static BiFunction<Integer, Integer, Integer> addTwoIntegers(Integer i1, Integer i2) {
    // to aid to debugging
    System.out.println(String.format("In addTwoIntegers i1: %s, i2: %s", i1, i2)); 
    return new BiFunction<Integer, Integer, Integer>() {
        @Override
        public Integer apply(Integer i1, Integer i2) {
            // see the difference in value as you run
            System.out.println(String.format("In apply i1: %s, i2: %s", i1, i2)); 
            return i1 + i2;
        }
    };
}

Чтобы добавить к этому дальнейшую область действия i1 и i2 в качестве аргументов метода для *Метод 1017 * является локальным для метода внутри анонимного класса, который представляет собой ваш код.

Дальнейшее улучшение

Если бы вы реализовали добавление к Integer s (и возврат * 1023)*), альтернативным и более чистым способом было бы определить BinaryOperator<Integer> в области видимости, где вы, возможно, собираетесь использовать реализацию как:

BinaryOperator<Integer> addTwoIntegers = Integer::sum; // (a,b) -> a+b

, а затем использоватьэто просто как

System.out.println("addTwoIntegers: " + addTwoIntegers.apply(5, 7));
0 голосов
/ 25 февраля 2019

Объявления не эквивалентны.Из-за переменной тени первый метод можно преобразовать в функцию как:

public static BiFunction<Integer, Integer, Integer> addTwoIntegers(Integer i1, Integer i2) {
    return (i1x, i2x) -> i1x + i2x;
}

Второе выражение функции метода относится к addTwoIntegers2 параметрам метода i1 и i2 вместопараметры функции i1x и i2x.i1 доступны i2 в закрытии функции, так как они оба 0, результат равен 0.

...