Java 8 – Lambdas (Closures)

Während in Java häufig nur von Lambdas gesprochen wird, handelt es sich bei Lambdas um die in Java umgesetzte Variante von Closures, deswegen sollten wir hier einen kurzen Blick auf Closures werfen.

Was ist eine Closure? Eine Closure – ja das Wort ist feminin – ist ein Konstrukt aus der Softwareentwicklung, bei der eine Funktion Zugriff auf seinen Erstellungskontext hat – hää wie jetzt? Na gut, etwas mehr Info anhand eines Beispiels (Quelle des Beispielcodes):

In dem Beispiel (zum Github-Repository) gibt es eine Funktion make_fun(), diese hat als Rückgabe eine anonyme Funktion, hierfür ist Lambda ein Synonym, häufig fällt in diesem Kontext gerade bei JavaScript und PHP der Begriff des Callbacks. Wie zu sehen ist, kann die zurückgegebene Funktion (der Teil in den geschweiften Klammern) auf die lokale Variable n zugreifen und diese sogar verändern, obwohl sie außerhalb des eigentlichen Funktionskontextes liegt, dem sogenannten Erstellungskontext. Die Funktion make_fun hat in der Methodensignatur keinen Funktionsparameter und einen Rückgabewert vom Typ Function<Integer, Integer>, was zugegeben auch zu erwarten war, da wir eine anonyme Funktion erstellen. Ein Blick hinter die Kulissen des Typs zeigt:

Wobei T der Typ des Parameters für die Funktion und R der Typ des Rückgabewertes der Funktion ist. Die Schreibweise ist etwas gewöhnungsbedürftig für Neulinge im Feld der funktionalen Programmierung, aber nach kurzer Eingewöhnungsphase doch verständlich. Die Invocation unserer Funktion findet anschließend durch den Aufruf der apply-Methode statt. Hierbei wird die Methode auf die übergebenen Werte angewendet – beispielhaft mit 5 Werten in zwei Durchläufen.

Zu sehen ist, dass sowohl der Callback auf der Variablen x als auch auf der Variablen y ihre eigene Variable n haben (wovon wir auch ausgegangen sind), sich der Inhalt der Variablen aber nicht ändert. Sollte nun versucht werden, den Wert von n innerhalb des Callbacks zu verändern, beispielsweise durch n += arg;, so wirft der Compiler (JIT Compiler) direkt einen Fehler:

Das bedeutet, dass die in Java verfügbaren Closures in Form von Lambdas keine Variablen sondern Wert geschlossenen Closures sind (Zur Erinnerung eine Closure ist ein über Speicherstruktur und Funktion geschlossenes Konstrukt).

Wenn eine Variable verändert werden muss, kann dies durch ein auf dem Heap abgelegtes Objekt etabliert werden:

Bringen wir diesen Code nun mit unseren beiden Beispielen zur Ausführung erhalten wir folgendes Ergebnis, in dem wir auch die außerhalb der Funktion gelagerten Variablen bearbeiten können, da der Compiler hier lediglich die Änderung der Referenz innerhalb der Funktion prüft (probiere einfach, myWrapperClass innerhalb der anonymen Methode neu zu instanziieren):

Wenn man hierbei noch Concurrency-Probleme beachtet (mutable shared state), hat man durch einen kleinen Umweg genau das, was ein Closure ausmacht.

Trotzdem sind Lambdas sicherlich eine sehr sinnvolle Neuerung in Java8.

Der Programmcode kann im Github-Repository gecloned werden. Der relevante Beispielcode findet sich im Package java_8_class_2.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.