Le espressioni lambda non cambiano l'insieme di problemi che puoi risolvere con Java in generale, ma sicuramente facilitano la risoluzione di alcuni problemi, proprio per lo stesso motivo per cui non programmiamo più in linguaggio assembly. Rimuovere le attività ridondanti dal lavoro del programmatore semplifica la vita e consente di fare cose che altrimenti non toccheresti nemmeno, solo per la quantità di codice che dovresti produrre (manualmente).
Ma le espressioni lambda non salvano solo righe di codice. Le espressioni lambda ti consentono di definire funzioni , qualcosa per cui potresti usare classi interne anonime come soluzione alternativa, ecco perché puoi sostituire classi interne anonime in questi casi, ma non in generale.
In particolare, le espressioni lambda sono definite indipendentemente dall'interfaccia funzionale a cui verranno convertite, quindi non ci sono membri ereditati a cui potrebbero accedere, inoltre, non possono accedere all'istanza del tipo che implementa l'interfaccia funzionale. All'interno di un'espressione lambda, this
e super
hanno lo stesso significato del contesto circostante, vedere anche questa risposta . Inoltre, non è possibile creare nuove variabili locali che ombreggiano le variabili locali del contesto circostante. Per il compito previsto di definire una funzione, questo rimuove molte fonti di errore, ma implica anche che per altri casi d'uso, potrebbero esserci classi interne anonime che non possono essere convertite in un'espressione lambda, anche se implementa un'interfaccia funzionale.
Inoltre, il costrutto new Type() { … }
garantisce di produrre una nuova istanza distinta (come new
sempre fa). Le istanze anonime della classe interna mantengono sempre un riferimento alla loro istanza esterna se create in un non static
contesto. Al contrario, le espressioni lambda catturano solo un riferimento a this
quando necessario, cioè se accedono this
o un non static
membro. E producono istanze di un'identità intenzionalmente non specificata, che consente all'implementazione di decidere in fase di runtime se riutilizzare istanze esistenti (vedere anche " Un'espressione lambda crea un oggetto sull'heap ogni volta che viene eseguita? ").
Queste differenze si applicano al tuo esempio. Il tuo costrutto della classe interna anonima produrrà sempre una nuova istanza, inoltre potrebbe catturare un riferimento all'istanza esterna, mentre la tua (Developer o1, Developer o2) -> o1.getName().compareTo(o2.getName())
è un'espressione lambda non di acquisizione che verrà valutata come un singleton nelle implementazioni tipiche. Inoltre, non produce un .class
file sul tuo disco rigido.
Date le differenze riguardanti sia la semantica che le prestazioni, le espressioni lambda possono cambiare il modo in cui i programmatori risolveranno determinati problemi in futuro, ovviamente, anche a causa delle nuove API che abbracciano idee di programmazione funzionale utilizzando le nuove funzionalità del linguaggio. Vedere anche Espressione lambda Java 8 e valori di prima classe .
(o1, o2) -> o1.getName().compareTo(o2.getName())