---
title: 'Syntax für Lambda-Ausdrücke'
url: 'https://www.tutego.de/blog/javainsel/2014/03/java-8-syntax-lambda-ausdruecke'
markdown: 'https://www.tutego.de/blog/javainsel/2014/03/java-8-syntax-lambda-ausdruecke.md'
date: '2014-03-21'
description: 'Lambda-Ausdrücke haben wie Methoden mögliche Parameter- und Rückgabe-Werte. Die Java-Grammatik für die Schreibweise von Lambda-Ausdrücken sieht ein paar nützliche syntaktische Abkürzungen vor. Ausführliche Schreibweise Lambda-Ausdrücke lassen sich auf unterschiedliche Arten und Weisen schreiben, da…'
taxonomy:
  category:
    - Insel
    - 'Java 8'
---

# Syntax für Lambda-Ausdrücke

![Illustration einer tropischen Insel mit Palmen und einem hohen Berg](https://www.tutego.de/blog/javainsel/user/themes/tutego/images/insel-cover.jpg)# Java Blog für Programmierer

[Java Blog für Programmierer](https://www.tutego.de/blog/javainsel/)

## Syntax für Lambda-Ausdrücke

21.03.2014 · [Christian Ullenboom](https://www.tutego.de/blog/javainsel/author/admin/)

Lambda-Ausdrücke haben wie Methoden mögliche Parameter- und Rückgabe-Werte. Die Java-Grammatik für die Schreibweise von Lambda-Ausdrücken sieht ein paar nützliche syntaktische Abkürzungen vor.

#### Ausführliche Schreibweise

Lambda-Ausdrücke lassen sich auf unterschiedliche Arten und Weisen schreiben, da es für diverse Konstruktionen Abkürzungen gibt. Eine Form, die jedoch immer gilt ist:

‚(‚ *LambdaParameter* ‚)‘ ‚->‘ ‚{‚ *Anweisungen* ‚}‘

Der Lambda-Parameter besteht (voll ausgeschrieben) wie ein Methodenparameter aus a) dem Typ, b) dem Namen und c) optionalen Modifizieren.

Der Parametername öffnet einen neuen Gültigkeitsbereich für eine Variable, wobei der Parametername *keine* anderen Namen von lokalen Variablen überlagern darf. Hier verhält sich die Lambda-Parametervariable wie eine neue Variable aus einem inneren Block und nicht wie eine Variable aus einer inneren Klasse, wo die Sichtbarkeit anders ist.

Beispiel

Folgendes gibt einen Compilerfehler im Lambda-Ausdruck, weil var schon deklariert ist, die Parametervariable vom Lambda-Ausdruck muss also „frisch“ sein:

```java
String var = "";
var.chars().forEach( var -> { System.out.println( var ); } );  //  Compilerfehler
```

#### Abkürzung 1: Typinferenz

Der Java-Compiler kann viele Typen aus dem Kontext ablesen, was Typ-Inferenz genannt wird. Wir kennen so etwas vom Diamant-Operator, wenn wir etwa schreiben `List`<`String`> list = new `ArrayList`<>().

Sind für den Compiler genug Typ-Informationen verfügbar, dann erlaubt der Compiler bei Lambda-Ausdrücken eine Abkürzung. Bei

```java
Comparator c =
  (String s1, String s2) -> { return s1.trim().compareTo( s2.trim() ); };
```

ist Typ-Inferenz einfach (`Comparator`<`String`> sagt alles aus), daher funktioniert die folgende Abkürzung:

```java
Comparator c = (s1, s2) -> { return s1.trim().compareTo( s2.trim() ); };
```

Die Parameterliste enthält also entweder explizit deklarierte Parametertypen oder implizite inferred-Typen. Eine Mischung ist nicht erlaubt, der Compiler blockt so etwas wie (`String` s1, s2) oder (s1, `String` s2) mit einem Fehler ab.

Wenn der Compiler die Typen ablesen kann, sind die Parametertypen optional. Aber Typ-Inferenz ist nicht immer möglich, weshalb die Abkürzung nicht immer möglich ist. Außerdem hilft die explizite Schreibweise auch der Lesbarkeit: kurze Ausdrücke sind nicht unbedingt die verständlichsten.

Hinweis

Der Compiler liest aus den Typen ab, ob alle Eigenschaften vorhanden sind. Die Typen sind dabei entweder explizit oder implizit gegeben.

```java
Comparator sc = (a, b) -> { return Integer.compare( a.length(), b.length() ); };
Comparator bc = (a, b) -> { return Integer.compare( a.length(), b.length() ); };
```

Die Klassen `String` und BitSet besitzen beide die Methode `length()`, daher ist der Lambda-Ausdruck korrekt. Der gleiche Lambda-Code lässt sich für zwei völlig verschiedene Klassen einsetzen, die überhaupt keine Gemeinsamkeiten haben, nur das sie zufällig beide eine Methode namens `length()` besitzen.

#### Abkürzung 2: Lambda-Rumpf ist entweder einzelner Ausdruck oder Block

Besteht der Rumpf eines Lambda-Ausdrucks nur aus einem einzelnen Ausdruck, kann eine verkürzte Schreibweise die Block-Klammern und das Semikolon einsparen. Statt

```
( LambdaParameter ) -> { return *Ausdruck;* }
```

heißt es dann

( *LambdaParameter* ) -> *Ausdruck*

Lambda-Ausdrücke mit einer return–Anweisung im Rumpf kommen häufig vor, da dies den typischen Funktionen entspricht. Somit ist es eine willkommene Verkürzung, wenn die abgekürzte Syntax für Lambda-Ausdrücke lediglich den Ausdruck fordert, der dann die Rückgabe bildet.

Hier sind drei Beispiele:

```
Lange SchreibweiseAbkürzung(s1, s2) -> { return s1.trim().compareTo( s2.trim() ); }
```

(s1, s2) -> `s1.trim()`.`compareTo`( `s2.trim()` )

```java
(a, b) -> { return a + b; }(a, b) -> a + b() -> { System.out.println(); }() -> System.out.println()
```

Ausführliche und abgekürzte Schreibweise

Ausdrücke können in Java auch zu void ausgewertet werden, sodass ohne Probleme ein Aufruf wie `System.out.println()` in der kompakten Schreibweise ohne Block gesetzt werden kann. Das heißt, wenn Lambda-Ausdrücke mit der kurzen Ausdrucks-Syntax eingesetzt werden, können diese Ausdrücke etwas zurückgeben, müssen aber nicht.

Hinweis

Die Schreibweise mit den geschweiften Klammern und den Rückgabe-Ausdrücken kann nicht gemischt werden. Entweder gibt es ein Block geschweifter Klammern und return oder keine Klammern und kein return-Schlüsselwort. Fehler ergeben also diese falschen Mischungen:

```java
Comparator c;
c = (s1, s2) -> { s1.trim().compareTo( s2.trim() ) };    // Compilerfehler (1)
c = (s1, s2) -> return s1.trim().compareTo( s2.trim() ); // Compilerfehler (2)
```

Würden wir in (1) ein explizites return nutzen wäre alles in Ordnung, würde bei (2) das return wegfallen wäre die Zeile auch compilierbar.

Ob Lambda-Ausdrücke eine Rückgabe haben, drücken zwei Begriffe aus:

- void-kompatibel: Der Lambda-Rumpf gibt kein Ergebnis zurück. Entweder weil der Block kein return enthält, oder ein return ohne Rückgabe, oder weil ein void-Ausdruck in der verkürzten Schreibweise eingesetzt wird. Der Lambda-Ausdruck () -> `System.out.println()` ist also void-kompatibel, genauso wie () -> {}.
- Wert-kompatibel: Der Rumpf beendet den Lambda-Ausdruck mit einer return-Anweisung, die einen Wert zurückgibt oder besteht aus der kompakten Schreibenweise mit einer Rückgabe ungleich void.

Eine Mischung aus void- und Wert-kompatibel ist nicht erlaubt und führt wie bei Methoden zu einem Compilerfehler.[\[1\]](file:C:/Users/Christian/Dropbox/Eigene%20Dokumente/Insel/todo/1.Lambdas,%20JPB,%20ISP,%20JM,%20zu%20MS.doc#_ftn1)

#### Abkürzung 3: Einzelner Identifizierer statt Parameterliste und Klammern

Besteht die Parameterliste

a) nur aus einem einzelnen Identifizierer und

b) ist der Typ durch Typ-Inferenz klar,

können die runden Klammern wegfallen.

Lange SchreibweiseTypen `inferredVollständig` `abgekürzt(String s)` -> `s.length()`(s) -> `s.length()`s -> `s.length()`(int i) -> `Math.abs( i )`(i) -> `Math.abs( i )`i -> `Math.abs( i )`

Unterschiedlicher Grad von Abkürzungen

Kommen alle Abkürzungen zusammen, lässt sich etwa die Hälfte an Code einsparen. Aus (int i) -> { return `Math.abs( i )`; } wird einfach i -> `Math.abs( i )`.

Syntax-Hinweis

Nur bei genau einem Lambda-Parameter können die Klammern weggelassen werden, da es sonst Mehrdeutigkeiten gibt, für die es sonst wieder komplexe Regeln zur Auflösung geben müsste. Heißt es etwa foo( k, v -> { … } ) ist es unklar, ob foo zwei Parameter deklariert. Ist das zweite Argument ein Lambda-Ausdruck, oder handelt es sich um nur genau einen Parameter, wobei dann ein Lambda-Ausdruck übergeben wird, der selbst zwei Parameter deklariert. Um Probleme wie diesen aus dem Weg zu gehen, können Entwickler auf den ersten Blick sehen, dass foo( k, v -> { … } ) eindeutig für Parameter steht, und foo( (k, v) -> { … } ) nur einen Parameter besitzt.

Kategorien: [Insel](https://www.tutego.de/blog/javainsel/category/insel/), [Java 8](https://www.tutego.de/blog/javainsel/category/java-8/)

[← Alle Beiträge](https://www.tutego.de/blog/javainsel/)

---

## Navigation

- Previous: [Java 8 Syntax-Migration mit Eclipse](https://www.tutego.de/blog/javainsel/2014/03/java-8-syntax-migration-mit-eclipse.md)
- Next: [Die Umgebung der Lambda-Ausdrücke und Variablenzugriffe](https://www.tutego.de/blog/javainsel/2014/03/java-8-umgebung-lambda-ausdruecke-variablenzugriffe.md)
