38 votes

Pourquoi les instructions "throw" doivent-elles être entourées d'un bloc de code complet dans un corps lambda ?

Si une fonction lambda ne contient qu'une seule déclaration, nous pouvons omettre de définir le bloc de code complet correspondant :

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

Pourquoi n'est-ce pas le cas pour les déclarations qui lancent des exceptions ? Il en résulte une erreur de compilation indiquant '{' expected :

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

Bien entendu, l'inclusion du corps de la lambda dans un bloc de code fonctionne :

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

25voto

Eugene Points 6271

AFAIK Les jls dit que le corps lambda doit être :

expression ou un bloc . Le faire de cette manière :

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

n'est ni l'un ni l'autre et le compilateur d'une manière ou d'une autre vous informe à ce sujet.

Le déclarer ainsi :

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

en fait un bloc. Voici la partie pertinente :

Un bloc est une séquence d'instructions, de déclarations de classes locales et de déclarations de variables locales. entre accolades .

21voto

holi-java Points 15887

Dans Java8, la grammaire d'un corps lambda n'accepte qu'un expression ou un bloc . Considérant que lever une exception est un déclaration et non un expression .

throwStatement: 'throw' expression ';' ;

lambdaBody: expression | block;

expression: lambdaExpression | assignmentExpression;

block : '{' blockStatements? '}' ;

On pourrait peut-être l'améliorer en y ajoutant throwStatement en lambdaBody dans la prochaine version du jdk si cela est nécessaire. En effet, nous en avons besoin comme vous l'avez mentionné plus haut. par exemple :

lambdaBody: expression | block | throwStatement;

15voto

manouti Points 10398

A throw est, en effet, une déclaration et non une expression, et doit donc être placée entre accolades. Selon la norme cet article À l'époque, le groupe d'experts Java a mené une enquête informelle sur la syntaxe des lambdas, et quatre options ont été proposées :

  • Homme de paille : #(arglist)(expr) and #(arglist){statements}
  • BGGA : { args -> statements } (similaire à Scala et Groovy)
  • SotL : #{ args -> statements}
  • Redmond : (args) -> { statements }

Finalement, le choix s'est porté sur une syntaxe similaire à celle de C# selon ce fil qui, d'après ce que j'ai pu voir, se rapproche le plus de la dernière option ci-dessus. En C#, il existe une distinction entre expression lambdas y déclaration lambdas :

Expression lambda (C#) :

(input parameters) => expression

Déclaration lambda (C#) :

(input parameters) => {statement;}  

La syntaxe est expliquée dans cette page de documentation MSDN .

Les raisons du choix de cette syntaxe par rapport aux autres options sont mentionnées dans le fil de discussion précédent :

La décision de choisir cette syntaxe était double :

  • La syntaxe obtient un score "assez bon" pour la plupart des su a des cas où elle semble mauvaise, comme toutes les autres). En particulier, elle en particulier, elle se débrouille bien avec les "petits" lambdas qui sont utilisés comme (un cas courant), ainsi qu'avec les grands lambdas de type (plusieurs déclarations).

  • Malgré des recherches approfondies, il n'y a pas eu de vainqueur parmi les (chaque forme présentait certains aspects positifs et d'autres vraiment pas [ ] les autres). Nous avons donc estimé qu'il valait mieux choisir quelque chose qui avait déjà été utilisé dans le passé. déjà fait ses preuves dans les deux langages qui se rapprochent le plus de Java -- C# et Scala -- plutôt que d'inventer quelque chose de nouveau.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X