Java8 лямбда против анонимных классов
Я немного изучил это и нашел несколько интересных примеров того, как лямбда-выражения будут систематически заменять эти классы, например метод сортировки коллекции, который использовался для получения анонимного экземпляра Comparator для выполнения сортировки:
Collections.sort(personList, new Comparator<Person>(){
public int compare(Person p1, Person p2){
return p1.firstName.compareTo(p2.firstName);
}
});
теперь можно сделать с помощью Lambdas:
Collections.sort(personList, (Person p1, Person p2) -> p1.firstName.compareTo(p2.firstName));
и выглядит удивительно лаконично. Итак, мой вопрос: есть ли причина продолжать использовать эти классы в Java8 вместо Lambdas?
EDIT
тот же вопрос, но в противоположном направлении, каковы преимущества использования лямбд вместо анонимных классов, поскольку лямбды могут использоваться только с интерфейсами одного метода, является ли эта новая функция только ярлыком, используемым только в мало случаев или это действительно полезно?
5 ответов:
анонимный внутренний класс (AIC) может быть использован для создания подкласса абстрактного класса или конкретного класса. AIC может также обеспечить конкретную реализацию интерфейса, включая добавление состояния (полей). На экземпляр AIC можно ссылаться с помощью
thisв его телах методов, поэтому на нем могут быть вызваны дальнейшие методы, его состояние может быть изменено с течением времени и т. д. Ни один из них не относится к лямбдам.Я бы предположил, что большинство применений AICs должны были обеспечить реализации без состояния отдельных функций и поэтому могут быть заменены лямбда-выражениями, но есть и другие применения AICs, для которых лямбды не могут использоваться. AICs здесь, чтобы остаться.
обновление
еще одно различие между AICS и лямбда-выражениями заключается в том, что AICs вводит новую область. То есть имена разрешаются из суперклассов и интерфейсов AIC и могут затенять имена, которые происходят в лексически заключающей среде. Для лямбд, все имена разрешаются лексически.
лямбды, хотя отличная функция, будет работать только с типами SAM. То есть взаимодействует только с одним абстрактным методом. Это не сработает, как только ваш интерфейс содержит более 1 абстрактного метода. Вот где анонимные классы будут полезны.
так, нет, мы не можем просто игнорировать анонимные классы. И просто FYI, код
sort()метод можно упростить, пропустив объявление типа дляp1иp2:Collections.sort(personList, (p1, p2) -> p1.firstName.compareTo(p2.firstName));вы также можете использовать метод ссылка здесь. Либо вы добавляете
compareByFirstName()методPersonкласса, и использовать:Collections.sort(personList, Person::compareByFirstName);или добавьте геттер для
firstName, непосредственно получитьComparatorСComparator.comparing()способ:Collections.sort(personList, Comparator.comparing(Person::getFirstName));
лямбда-производительность с анонимными классами
при запуске приложения каждый файл класса должен быть загружен и проверен.
анонимные классы обрабатываются компилятором как новый подтип для данного класса или интерфейса, поэтому для каждого будет создан новый файл класса.
лямбды отличаются при генерации байт-кода, они более эффективны, используются invokedynamic инструкция, которая поставляется с JDK7.
Для Лямбды эта инструкция используется для задержки перевода лямбда-выражения в байт-код до времени выполнения. (инструкция будет вызвана только в первый раз)
в результате лямбда-выражение станет статическим методом (созданным во время выполнения). (Есть небольшая разница с stateles и statefull cases, они разрешаются с помощью сгенерированных аргументов метода)
есть следующие различия:
1 синтаксис)
лямбда-выражения выглядят аккуратно по сравнению с анонимным внутренним классом (AIC)
public static void main(String[] args) { Runnable r = new Runnable() { @Override public void run() { System.out.println("in run"); } }; Thread t = new Thread(r); t.start(); } //syntax of lambda expression public static void main(String[] args) { Runnable r = ()->{System.out.println("in run");}; Thread t = new Thread(r); t.start(); }2) Scope
анонимный внутренний класс является классом, что означает, что он имеет область для переменной, определенной внутри внутреннего класса.
а,лямбда-выражение не является собственной областью, но является частью заключающей области.
аналогичное правило применяется для супер и этой ключевое слово при использовании внутри анонимного внутреннего класса и лямбда-выражения. В случае анонимного внутреннего класса это ключевое слово относится к локальной области, а супер ключевое слово относится к суперклассу анонимного класса. В то время как в случае лямбда-выражения это ключевое слово относится к объекту типа enclosing, а super будет ссылаться на суперкласс класса enclosing.
//AIC public static void main(String[] args) { final int cnt = 0; Runnable r = new Runnable() { @Override public void run() { int cnt = 5; System.out.println("in run" + cnt); } }; Thread t = new Thread(r); t.start(); } //Lambda public static void main(String[] args) { final int cnt = 0; Runnable r = ()->{ int cnt = 5; //compilation error System.out.println("in run"+cnt);}; Thread t = new Thread(r); t.start(); }3) Производительность
во время выполнения анонимные внутренние классы требуют загрузки класса, выделения памяти и инициализации объекта и вызова нестатического метода, в то время как лямбда-выражение является чистым действием времени компиляции и не требует дополнительных затрат во время выполнения. Так что производительность лямбда-выражения лучше по сравнению с анонимными внутренними классами.**
**Я понимаю, что это не совсем верно . Пожалуйста, см. Следующий вопрос. лямда против анонимная производительность внутреннего класса: снижение нагрузки на загрузчик классов?
лямбда в java 8 был введен для функционального программирования. Где вы можете избежать шаблонного кода. Я наткнулся на эту интересную статью о лямбде.
http://radar.oreilly.com/2014/04/whats-new-in-java-8-lambdas.html
рекомендуется использовать лямбда-функции для простых логик. Если реализация сложной логики с использованием лямбд будет накладными расходами при отладке кода в случае возникновения проблемы.
Comments