relacion propiedades programacion origen operaciones numeros matematicas los historia entre ejemplos concepto complejos aplicadas java exception lambda java-8

java - propiedades - ¿Por qué debe arrojar sentencias encerradas con un bloque de código completo en un cuerpo lambda?



origen de los numeros complejos (3)

Si hay una sola instrucción en una función lambda, podemos omitir la definición del bloque de código completo para ello:

new Thread(() -> System.out.println());

¿Por qué no es ese el caso de las declaraciones que arrojan excepciones? Esto produce un error de compilación que indica ''{'' expected :

new Thread(() -> throw new RuntimeException());

Por supuesto, encierra 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 . Teniéndolo así:

new Thread(() -> throw new RuntimeException());

no es ninguno y el compilador de alguna manera te informa sobre eso.

Declararlo así:

new Thread(() -> { throw new RuntimeException(); });

lo convierte en un bloque. Aquí está la parte relevante:

Un bloque es una secuencia de declaraciones, declaraciones de clases locales y declaraciones de declaraciones de variables locales dentro de llaves .


En Java8, la gramática de un cuerpo lambda solo acepta una expression o un block . 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 incluyendo throwStatement en lambdaBody en la próxima versión jdk si es necesario. De hecho, necesitamos eso como lo mencionó anteriormente. por ejemplo:

lambdaBody: expression | block | throwStatement;


Una declaración de 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:

  • Strawman : #(arglist)(expr) and #(arglist){statements}
  • BGGA : { args -> statements } (similar a Scala y Groovy)
  • SotL : #{ args -> statements}
  • Redmond : (args) -> { statements }

Finalmente, la elección fue adoptar una sintaxis similar a la de C # de acuerdo con este hilo , que también se parece más a la última opción que he visto anteriormente. En C #, hay una distinción entre la expresión lambdas y la declaración lambdas :

Expresión lambda (C #):

(input parameters) => expression

Declaración lambda (C #):

(input parameters) => {statement;}

La sintaxis se explica en esta página de documentación de MSDN .

Y la razó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 las lambdas "pequeñas" que se usan como argumentos de método (un caso común), y también funciona bien con las lambdas grandes (multi-declaraciones).

  • A pesar de una extensa búsqueda, no hubo un ganador claro entre las alternativas (cada forma tenía algunos aspectos buenos y algunos realmente no muy buenos, y no había ninguna forma que fuera claramente mejor que las demás). Por lo tanto, sentimos que era mejor elegir algo que ya se haya demostrado que funciona bien en los dos idiomas que más se parecen a Java, C # y Scala, en lugar de inventar algo nuevo.