В чем преимущество лямбда-выражений перед переменными метода? - PullRequest
1 голос
/ 02 августа 2020

Я новичок в лямбда-выражениях, так что потерпите меня. Скажем, у меня есть интерфейс с одной абстрактной функцией:

public interface IAbsFunc {
    public abstract void absFunc(int x);
}

В этом случае я могу сохранить лямбда-выражение в переменной:

public class Lambda {
    public static void main(String[] args) {
        IAbsFunc obj = (int x) -> System.out.println(x);
        obj.absFunc(3);
    }
}

Если я правильно понимаю , это похоже на сохранение метода в переменной. Однако это уже можно сделать с помощью java .lang.reflect:

public class Lambda {
    public static void main(String[] args) throws Exception {
        Method obj = PrintStream.class.getDeclaredMethod("println", int.class);
        obj.invoke(System.out, 3);
    }
}

Ясно, что здесь что-то не хватает. В какой ситуации лямбда-выражение было бы предпочтительнее?

Ответы [ 2 ]

5 голосов
/ 02 августа 2020

Вы должны понимать, что такое API отражений для . Он создан для того, чтобы вы могли делать то, что невозможно или сложно сделать с другими языковыми функциями.

Официальная документация утверждает один (и IMO самый важный) вариант использования:

Отладчики должны иметь возможность проверять закрытые члены в классах. Тестовые жгуты могут использовать отражение для систематического вызова API-интерфейсов обнаруживаемого набора, определенного в классе, чтобы обеспечить высокий уровень покрытия кода в тестовом наборе.

Таким образом, использование отражений может быть очень полезным при тестировании где вы хотите иметь полный доступ к тестируемому коду. Вы получаете доступ к private методам и полям, вы можете изменять final полей и так далее. В документации указывается один большой недостаток:

Поскольку отражение включает типы, которые разрешаются динамически, некоторые оптимизации Java виртуальных машин не могут быть выполнены. Следовательно, отражающие операции имеют более низкую производительность, чем их неотражающие аналоги, и их следует избегать в тех частях кода, которые часто вызываются в приложениях, чувствительных к производительности.

Гибкость сопровождается недостатками производительности. Есть и другие варианты использования и недостатки, которые вы можете найти в документации, которую я связал.

Использование лямбда здесь в вашем случае - это как раз то, для чего предполагается использовать лямбда (помимо прочего). Использование отражений здесь просто не то, для чего они нужны. Можно, но нельзя.

2 голосов
/ 07 августа 2020

@ akuzminykh объяснил, почему нельзя хорошо использовать отражение. Однако вы спрашивали о преимуществах лямбда-выражений:

  • stati c проверка типа (в отличие от строкового литерала, который является очень плохим кодом кода)
  • скорость (медленное отражение)
  • нет необходимости в обработке ReflectiveOperationException с
  • вызывающему лямбда-выражению не нужно знать экземпляр, на котором должен выполняться метод ( System.out), т.е. Method#invoke имеет 2 параметра, а IAbsFunc#absFunc только один.
    • Не требуется, чтобы был объектом для вызова метода в первую очередь. Вы можете поместить более 1 оператора в лямбда-выражение, но с отражением вам нужно будет определить другой метод только для обертывания 2 операторов, очень многословно.
  • можно использовать как параметр обратного вызова в методе
  • вы можете использовать ссылки на методы, поэтому это может быть IAbsFunc f = System.out::println;

Вы должны прочитать функциональное программирование , это очень полезный концепция. Lambdas также используют концепцию, называемую замыканием, они запоминают (эффективно) конечные переменные из области, в которой они были определены.

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