Si hay una sola declaración en una función lambda, podemos omitir la definición del bloque de código completo para ella:
new Thread(() -> System.out.println()); ¿Por qué no es ese el caso de las declaraciones que lanzan excepciones? Esto produce un error de compilación que indica '{' expected :
new Thread(() -> throw new RuntimeException());Por supuesto, encerrar el cuerpo lambda en un bloque de código funciona:
new Thread(() -> { throw new RuntimeException(); });AFAIK El jls dice que el cuerpo lambda tiene que ser:
expresión o un bloque . Tenerlo así:
new Thread(() -> throw new RuntimeException());no es ninguno y el compilador de alguna manera te informa sobre eso.
Declarándolo así:
new Thread(() -> { throw new RuntimeException(); });lo convierte en un bloque. Aquí está la parte relevante:
Un bloque es una secuencia de instrucciones, declaraciones de clases locales y declaraciones de variables locales entre llaves .
En Java8, la gramática de un cuerpo lambda solo acepta una expresión o un bloque . Mientras que lanzar una excepción es una declaración , no una expresión .
throwStatement: 'throw' expression ';' ; lambdaBody: expression | block; expression: lambdaExpression | assignmentExpression; block : '{' blockStatements? '}' ; Tal vez se pueda mejorar al incluir throwStatement en lambdaBody en la próxima versión de jdk si es necesario. De hecho, lo necesitamos como mencionaste anteriormente. por ejemplo:
lambdaBody: expression | block | throwStatement;Una declaración throw es, bueno, una declaración y no una expresión, por lo que debe colocarse entre llaves. Según este artículo , el Grupo de expertos de Java realizó una encuesta informal sobre la sintaxis de lambdas en ese momento, y había cuatro opciones:
#(arglist)(expr) and #(arglist){statements}{ args -> statements } (similar a Scala y Groovy)#{ args -> statements}(args) -> { statements }En última instancia, la elección fue adoptar una sintaxis similar a la de C# según este hilo , que también se parece más a la última opción anterior hasta donde puedo ver. En C#, hay una distinción entre expresión lambdas y declaración lambdas :
Expresión lambda (C#):
(input parameters) => expressionDeclaración lambda (C#):
(input parameters) => {statement;}La sintaxis se explica en esta página de documentación de MSDN .
Y la justificación para elegir esta sintaxis sobre las otras opciones se menciona en el hilo anterior:
La decisión de elegir esta sintaxis fue doble:
La sintaxis puntúa "bastante bien" en la mayoría de las medidas subjetivas (aunque tiene casos en los que se ve mal, al igual que todos los demás). En particular, funciona bien con lambdas "pequeñas" que se usan como argumentos de método (un caso común), y también funciona bien con lambdas grandes (de varias instrucciones).
A pesar de la extensa búsqueda, no hubo un ganador claro entre las alternativas (cada formulario tenía algunos aspectos buenos y algunos realmente no muy buenos, y no había ningún formulario que fuera claramente mejor que los demás). Por lo tanto, sentimos que era mejor elegir algo que ya se ha demostrado que funciona bien en los dos lenguajes que más se parecen a Java (C# y Scala) en lugar de inventar algo nuevo.