Es gibt einen neuen Hype mit den lang erwarteten Lambda-Ausdrücken in Java 8; alle 3 tage erscheint ein weiterer artikel mit ihnen darüber, wie cool sie sind.
Nach meinem Verständnis ist ein Lambda-Ausdruck nichts anderes als eine anonyme innere Klasse mit einer einzigen Methode (zumindest auf Bytecode-Ebene). Abgesehen davon gibt es eine weitere nette Feature - Typ - Inferenz, aber ich glaube, dass dies mit Generika auf einer bestimmten Ebene erreicht werden kann (natürlich nicht so ordentlich wie mit Lambda - Ausdrücken).
Wussten Sie, dass Lambda-Ausdrücke in Java mehr als nur eine syntaktische Zuckerung bringen? Kann ich leistungsfähigere und flexiblere Klassen oder andere objektorientierte Konstrukte mit Lambda-Ausdrücken erstellen, die mit den aktuellen Sprachfunktionen nicht erstellt werden können?
quelle
this
inOuterClass.this
ist Teil des Prozesses, bei dem Lambda-Ausdrücke in anonyme Klassen umgewandelt werden.Antworten:
tl; dr: Während es sich hauptsächlich um syntaktischen Zucker handelt, macht diese schönere Syntax viele Dinge praktisch, die früher in endlosen, unlesbaren Zeilen von Klammern und Klammern endeten.
Nun, es ist tatsächlich umgekehrt, da Lambdas viel älter als Java sind. Anonyme innere Klassen mit einer einzigen Methode sind (waren) die Java, die Lambdas am nächsten kamen. Es ist eine Annäherung, die für einige Zeit "gut genug" war, aber eine sehr unangenehme Syntax hat.
Auf der Oberfläche scheinen Java 8-Lambdas nicht viel mehr zu sein als syntaktischer Zucker, aber wenn Sie unter die Oberfläche schauen, sehen Sie Tonnen von interessanten Abstraktionen. Zum Beispiel der JVM - Spezifikation behandelt eine Lambda ganz anders als ein „true“ Objekt, und während Sie können behandeln , als ob sie , wo Objekte werden die JVM nicht als solche erforderlich umzusetzen.
Obwohl all diese technischen Tricks interessant und relevant sind (da sie zukünftige Optimierungen in der JVM ermöglichen!), Ist der eigentliche Vorteil "nur" der syntaktische Zuckerteil.
Was ist leichter zu lesen:
oder:
oder (mit einem Methodenhandle anstelle eines Lambda):
Die Tatsache, dass Sie endlich auf eine prägnante Weise ausdrücken können, bei der es sich zuvor um 5 Codezeilen handelt (von denen 3 äußerst langweilig sind), bringt eine echte Änderung des Praktischen mit sich (aber nicht des Möglichen, Zugegebenen).
quelle
List
kann jedes Objekt aufnehmen, AList<String>
kann "nur" Strings aufnehmen. Generika haben eine Einschränkung hinzugefügt (und die Option, Einschränkungen zu formalisieren!), Keine Erweiterung der Macht. Seit Java 1.1 war so ziemlich alles syntaktischer Zucker. Und das ist nicht unbedingt eine schlechte Sache.List<String>
ist nur einList
mit Besetzung,String
um einige Rückgabewerte hinzuzufügen. Trotzdem sind sie äußerst nützlich und haben das Schreiben in der Sprache wesentlich komfortabler gemacht. Lambdas sind ein ähnlicher Fall.Für Java ist es nichts weiter als eine bessere Möglichkeit, eine anonyme innere Klasse zu schaffen. Dies liegt an der fundamentalen Entscheidung in Java, dass jedes Bit des Bytecodes in einer bestimmten Klasse gespeichert werden muss, die nach Jahrzehnten alten Codes nicht mehr geändert werden kann.
Doch darum geht es in Lambda-Ausdrücken nicht wirklich. In Formalismen, in denen es sich eher um einheimische Konzepte als um eine Inszenierung handelt, sind Lambdas grundlegende Bausteine. Sowohl ihre Syntax als auch die Einstellung der Menschen zu ihnen sind sehr unterschiedlich. Das Beispiel einer anonymen rekursiven Funktion, die in Struktur und Interpretation von Computerprogrammen ausschließlich aus Lambda erstellt wurde, kann Ihre gesamte Vorstellung von Berechnung ändern. (Ich bin mir jedoch ziemlich sicher, dass das Erlernen des Programmierens einfach zu esoterisch ist, um jemals eine Mainstream-Erfolgsgeschichte zu werden.)
quelle
Ja, es ist nur ein syntaktischer Zucker, in dem Sinne, dass Sie überall, wo Sie ein Lambda schreiben, diesen Ausdruck mit einer Methode als anonymen inneren Klassenausdruck neu schreiben können, wobei die Klasse die für den Lambda-Kontext abgeleitete funktionale Schnittstelle implementiert, und es wäre semantisch genau gleichwertig. Und Sie können dies tun, indem Sie einfach den Lambda-Ausdruck durch den anonymen Klassenausdruck ersetzen, ohne einen anderen Ausdruck oder eine andere Codezeile zu ändern.
quelle
this
müssen in konvertiert werdenOuterClass.this
. Das widerspricht nicht dem, was ich gesagt habe - jeder Lambda- Ausdruck kann in einen semantisch äquivalenten anonymen Klassenausdruck umgewandelt werden , ohne dass etwas außerhalb dieses Ausdrucks geändert wird . Ich habe nicht gesagt, dass sich das Innere nicht ändern würde.this
Lambda ein Teil des syntaktischen Zuckers und kein Unterschied in der Semantik. Und über Unterschiede in der Implementierung, Implementierung! = Semantik. Über Unterschiede in der Objektidentität; Die Objektidentität ist äußerst tangential zur Funktionalität von Lambdas. niemand überprüft die Objektidentität von Lambdas / Anon-Klassen, da dies nicht sinnvoll ist.Joachim Sauer hat Ihre Frage bereits gut beantwortet und nur angedeutet, was ich für wichtig halte. Da Lambdas keine Klassen sind, werden sie auch nicht als solche kompiliert. Alle anonymen inneren Klassen führen zur Erstellung einer .class-Datei, die wiederum vom ClassLoader geladen werden muss. Die Verwendung von Lambdas verschönert also nicht nur Ihren Code, sondern verringert auch die Größe Ihres kompilierten Codes, den Speicherbedarf Ihres ClassLoader und die Zeit, die für die Übertragung der Bits von Ihrer Festplatte benötigt wird.
quelle
Nein sind sie nicht.
Ein anderer Weg ist, Lambdas sind ein nicht objektorientierter, aber prägnanter Weg, um dasselbe zu erreichen, was eine anonyme Klasse oder, wie ich es vorziehen würde, eine innere Klasse auf objektorientierte Weise erreichen würde.
quelle