Ein neues JDK Enhancement Proposal (JEP) beschäftigt sich mit der Verbesserung der Lambda Expressions in Java. Neben der Verwendung von Underscores wird eine bessere Disambiguierung für funktionale Ausdrücke vorgeschlagen.
Unter dem Namen JEP 302: Lambda Leftovers hat Maurizio Cimadamore, Consulting Member des Technical Staffs bei Oracle, drei Lambda-bezogene Verbesserungsvorschläge eingebracht. Lambda-Ausdrücke sind seit Java 8 fester Bestandteil der Sprache und führen funktionale Programmier-Konzepte in Java ein. Doch wie der JEP-Titel „Lambda Leftovers“ schon andeutet, gibt es hier noch Spielraum für mehr.
Und in der Tat: Würden die Vorschläge umgesetzt, die im JEP 302 enthalten sind, hieße das eine deutliche Anpassung der Lambda-Nutzung in Java an die in anderen Sprachen vorhandene. Drei Änderungen sind es, die von Cimadamore nun vorgeschlagen wurden:
In Java 8 wurde die Overload-Resolution komplett überarbeitet, um weiterreichende Interaktionen mit der Typen-Inferenz zu erlauben. Allerdings wurden die Möglichkeiten, beim Kompilieren den Lambda-Type abzuleiten, nicht vollständig ausgeschöpft. Maurizio Cimadamore beschreibt das Problem wiefolgt:
Specifically, the
(Java 8) compiler is not allowed to do:
- attribution of the lambda body
- overload resolution of the method reference
And as a result, the compiler’s ability to rule out inapplicable candidates is severely impaired.
Cimadamore verdeutlicht dies anhand des folgenden Beispiels:
m(Predicate<String> ps) { ... }
m(Function<String, String> fss) { ... }
m(s -> false) //ambiguous
Für den Programmierer ist es klar, welche überladene Methode hier gewählt werden sollte: Das Lambda gibt ein „false“ zurück, sodass Function<String, String>
zweifelsfrei inkompatibel ist. Das gilt aber nicht für den Java-8-Compiler, der sich lediglich die beiden Methoden anschaut, hier keinen Unterschied erkennt und somit ein Ambiguitätsproblem feststellt.
Solche und ähnliche Fälle sollen in Java 10 durch erweiterte Disambiguitätschecks geklärt werden, sodass der Compiler Lambda-Typen ableiten kann, wenn der Kontext genügend Informationen bereit stellt.
Der Underscore _
wird in vielen Sprachen genutzt, um einen unbenannten Lambda-Parameter zu kennzeichnen. Mit der Annahme von JEP 302 würde der Underscore diesen Zweck auch in Java erfüllen, beispielsweise:
BiFunction<Integer, String, String> biss = (i, _) -> String.valueOf(i);
Dies soll den Underscore unter anderem auch für die Kennzeichnung ungenutzter Methoden-Parameter frei machen.
In Java 8 dürfen Parameter von Lambda-Ausdrücken nicht dieselben Namen wie Variablen im sie umgebenden Scope tragen. Damit verhalten sich Lambdas bisher genauso wie while-Schleifen oder if-Statements. Abraham Marín Pérez gibt auf InfoQ ein einfaches Beispiel:
String s = "hello";
if(finished) {
String s = "bye"; // error, s already defined
}
Predicate<String> ps = s -> s.isEmpty(); // error, s already defined
Im JEP 302 wird nun vorgeschlagen, diese Restriktion zu lösen und ein, wie es dort genannt wird, „Shadowing of lambda parameters“ zu erlauben. Das folgende Beispiel zeigt das Problem auf:
Map<String, Integer> msi = ...
...
String key = computeSomeKey();
msi.computeIfAbsent(key, key -> key.length()) //error
Der Versuch, den Namen key
als Lambda-Parameter im Aufruf computeIfAbsent
zu verwenden, schlägt fehl, da es bereits eine Variable mit dem gleichen Namen im selbem Kontext gibt.
Wann und ob diese Änderungen umgesetzt werden, ist noch nicht abzusehen. Pérez gibt an, dass eine Integration in Java 10 denkbar wäre. Weitere Informationen zu JEP 302 gibt es im offiziellen Proposal und im Artikel von Abraham Marín Pérez auf InfoQ.