Wyrażenia lambda nie zmieniają ogólnie zestawu problemów, które można rozwiązać za pomocą Javy, ale zdecydowanie ułatwiają rozwiązywanie pewnych problemów, z tego samego powodu, dla którego nie programujemy już w języku asemblerowym. Usunięcie zbędnych zadań z pracy programisty ułatwia życie i pozwala robić rzeczy, których inaczej byśmy nawet nie tknęli, tylko dla ilości kodu, który musiałbyś wyprodukować (ręcznie).
Ale wyrażenia lambda to nie tylko zapisywanie wierszy kodu. Wyrażenia lambda umożliwiają definiowanie funkcji , w przypadku których wcześniej można było użyć anonimowych klas wewnętrznych jako obejścia, dlatego w takich przypadkach można zastąpić anonimowe klasy wewnętrzne, ale nie ogólnie.
Przede wszystkim wyrażenia lambda są definiowane niezależnie od interfejsu funkcjonalnego, na który będą konwertowane, więc nie ma dziedziczonych elementów, do których mogliby uzyskać dostęp, a ponadto nie mogą uzyskać dostępu do wystąpienia typu implementującego interfejs funkcjonalny. W wyrażeniu lambda this
i super
mają takie samo znaczenie jak w otaczającym kontekście, zobacz także tę odpowiedź . Nie można także tworzyć nowych zmiennych lokalnych, które przesłaniają zmienne lokalne otaczającego kontekstu. W przypadku zamierzonego zadania definiowania funkcji usuwa to wiele źródeł błędów, ale oznacza to również, że w innych przypadkach użycia mogą istnieć anonimowe klasy wewnętrzne, których nie można przekonwertować na wyrażenie lambda, nawet jeśli implementuje interfejs funkcjonalny.
Ponadto konstrukcja new Type() { … }
gwarantuje utworzenie nowej odrębnej instancji (jak new
zawsze). Anonimowe instancje klas wewnętrznych zawsze zachowują odniesienie do ich wystąpienia zewnętrznego, jeśli zostały utworzone w innym static
kontekście. W przeciwieństwie do tego wyrażenia lambda przechwytują odniesienie tylko this
wtedy, gdy jest to potrzebne, tj. Jeśli mają dostęp this
lub nie są static
członkami. Tworzą instancje celowo nieokreślonej tożsamości, co pozwala implementacji zdecydować w czasie wykonywania, czy ponownie wykorzystać istniejące instancje (zobacz także „ Czy wyrażenie lambda tworzy obiekt na stercie za każdym razem, gdy jest wykonywane? ”).
Te różnice dotyczą twojego przykładu. Twoja anonimowa konstrukcja klasy wewnętrznej zawsze będzie tworzyła nową instancję, może również przechwytywać odwołanie do instancji zewnętrznej, podczas gdy twoje (Developer o1, Developer o2) -> o1.getName().compareTo(o2.getName())
jest nieprzechwytywanym wyrażeniem lambda, które w typowych implementacjach zostanie oszacowane na singleton. Co więcej, nie tworzy .class
pliku na dysku twardym.
Biorąc pod uwagę różnice zarówno semantyczne, jak i wydajnościowe, wyrażenia lambda mogą zmienić sposób, w jaki programiści będą rozwiązywać pewne problemy w przyszłości, oczywiście również z powodu nowych interfejsów API obejmujących koncepcje programowania funkcjonalnego z wykorzystaniem nowych funkcji języka. Zobacz także wyrażenie lambda Java 8 i wartości pierwszej klasy .
(o1, o2) -> o1.getName().compareTo(o2.getName())