2012-06-21 10 views
16

Ich weiß, dass die Java-8-Lambda-Implementierung Änderungen unterliegt, aber in Lambda-Build b39 habe ich festgestellt, dass geschweifte Klammern nur weggelassen werden können, wenn der Lambda-Ausdruck einen nicht-void-Typ zurückgibt. Zum Beispiel stellt dies:Wann sind geschweifte Klammern optional in Java 8 Lambda-Syntax?

public class Collections8 { 
     public static void main(String[] args) { 
       Iterable<String> names = Arrays.asList("Alice", "Bob", "Charlie"); 
       names.filter(e -> e.length() > 4).forEach(e -> { System.out.println(e); }); 
     } 
} 

Aber die Klammern wie folgt zu entfernen:

names.filter(e -> e.length() > 4).forEach(e -> System.out.println(e)); 

gibt dem Fehler

Collections8.java:6: error: method forEach in interface Iterable<T> cannot be applied to given types; 
     names.filter(e -> e.length() > 4).forEach(e -> System.out.println(e)); 
             ^
    required: Block<? super String> 
    found: lambda 
    reason: incompatible return type void in lambda expression 
    where T is a type-variable: 
    T extends Object declared in interface Iterable 

Kann mir jemand erklären, was hier los?

+1

wenn es noch in der Entwicklung und Änderungen vorbehalten ist, warum sogar fragen? Die Antwort könnte sofort veraltet sein. – user12345613

+10

Weil ich gerne die Gründe dahinter verstehen würde. – hertzsprung

+1

Woher bekommen Sie die Filtermethode? Ich habe Java 8 Lambda Versin, und Jahr Code kompiliert nicht. – NimChimpsky

Antwort

18

Sie können die geschweiften Klammern weglassen, wenn der Lambda-Text ein einzelner Ausdruck oder ein Void-Methodenaufruf ist. Jeder Ausdruck wird als Wert ausgewertet und kann daher nicht ungültig sein.

Wenn der Körper des Lambdas ein Block von Anweisungen (zB eine Reihe von durch eine return Anweisung folgten Berechnungen) oder das Lambda keinen Wert hat (dh einen void Rückgabetyp) und ist nicht ein einzelner Hohlraum Methodenaufruf , müssen Sie die Blockform verwenden, die Klammern erfordert.

In einem Block-Stil lambda, wenn ein Wert ist return ed, dann sind alle möglichen Codepfade müssen entweder return ein Wert oder ein throwThrowable.

+1

Ich glaube, das ist nur zu wiederholen, was der OP sagte und fügt einige zusätzliche Details hinzu, ohne das angeforderte "warum" zu beantworten, es sei denn, ich verpasse etwas. –

+0

Ich denke, das klärt die Dinge für mich. Anweisungen sind keine Ausdrücke, da sie nicht ausgewertet werden können. Klammern sind optional, wenn der Lambda-Körper ein Ausdruck ist, aber sie sind obligatorisch, wenn der Körper eine Aussage oder eine Reihe von Aussagen ist. Klingt das richtig, @jpm? – hertzsprung

+2

Fast. Es sollte klargestellt werden, dass Ausdrücke eine Art von Anweisung sind (d. H. Alle Ausdrücke sind Anweisungen, aber nicht alle Anweisungen sind Ausdrücke). Beachten Sie auch, dass ein Block (Code, der von '{}' umgeben ist) syntaktisch eine einzelne Anweisung ist. Es mag klarer sein zu sagen, dass der Körper eines Lambda eine einzelne Aussage enthalten kann, die entweder ein Ausdruck oder eine Block-Aussage sein kann. – jpm

10

Das gerade in: der EG hat (meistens) eine Entscheidung über die Syntax getroffen.

Nachdem wir eine Reihe von Alternativen in Betracht gezogen hatten, entschieden wir uns, die C# -Syntax im Wesentlichen zu übernehmen. Wir können weiter über die Feinpunkte (z. B. dünner Pfeil gegen Fettpfeil, spezielle Nilarieform usw.) nachdenken, und haben noch keine Entscheidung über die Methodenreferenzsyntax getroffen.

Die C# Syntax:

lambda = ArgList Arrow Body 
ArgList = Identifier 
      | "(" Identifier [ "," Identifier ]* ")" 
      | "(" Type Identifier [ "," Type Identifier ]* ")" 
Body = Expression 
      | "{" [ Statement ";" ]+ "}" 

Ein Ausdruck auf etwas auswertet, kann man nicht haben Leere Ausdrücke in Java. Es ist eine Aussage, also brauchst du {} um es herum.

http://mail.openjdk.java.net/pipermail/lambda-dev/2011-September/003936.html

0

Wenn es keine Klammern sind, kehrt das Lambda automatisch einen Ausdruck nach dem Operator ->.
Wenn Sie also ein Lambda haben, das nichts zurückgibt, müssen Sie die Klammern verwenden

1

Ich habe Ihren Code versucht und für die aktuellste JRE-Version denke ich, es wäre in Ordnung.

Das Folgende ist, was ich von Oracle Java-Dokumenten referenziere.

In einem Lambda-Ausdruck müssen Sie Anweisungen in Klammern einschließen ({}). Sie müssen jedoch keinen void-Methodenaufruf in geschweifte Klammern einschließen.
Zum Beispiel ist die folgende gültige Lambda-Ausdruck:

email -> System.out.println(email) 

Und der Doc ganz klar erklärt. Hoffe, das kann dein Problem lösen.

Referenzen: https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html

Verwandte Themen