Java Lambdas et les Fermetures
J'entends les lambdas sont à venir pour Java près de chez vous (J8). J'ai trouvé un exemple de ce à quoi ils vont ressembler sur certains blog:
SoccerService soccerService = (teamA, teamB) -> {
SoccerResult result = null;
if (teamA == teamB) {
result = SoccerResult.DRAW;
}
else if(teamA < teamB) {
result = SoccerResult.LOST;
}
else {
result = SoccerResult.WON;
}
return result;
};
Donc droit au large de la chauve-souris:
- Où sont
teamA
etteamB
tapé? Ou ne sont-ils pas (comme certains bizarre forme de génériques)? - Est un lambda un type de fermeture, ou est-ce l'inverse?
- Quels seront les avantages que cela donne-moi plus d'un typique fonction anonyme?
Vous devez vous connecter pour publier un commentaire.
L'expression Lambda est juste sucre syntaxique pour mettre en œuvre une interface cible, cela signifie que vous allez mettre en œuvre une méthode particulière dans l'interface par le biais d'une expression lambda. Le compilateur peut déduire les types des paramètres dans l'interface et c'est pourquoi vous n'avez pas besoin de définir explicitement dans l'expression lambda.
Par exemple:
Dans cette expression, l'expression lambda évidemment implémente un
Comparator
de chaînes de caractères, par conséquent, cela implique que l'expression lambda est sucre syntaxique pour la mise en œuvre decompare(String, String)
.Ainsi, le compilateur peut supposer que le type de
s1
ets2
estString
.Votre cible type d'interface fournit toutes les informations que le compilateur a besoin de déterminer quels sont les types réels de la lambda paramètres.
Briant Goetz, le Langage Java Architecte à l'Oracle de la dite société a publié quelques articles de l'avancement des travaux dans le JDK 8 Lambdas. Je crois que les réponses à vos questions sont là:
Ce second article nous explique comment les expressions lambda sont mis en œuvre au niveau du bytecode et peut vous aider à plonger dans les détails de votre deuxième question.
Voir cette page pour une version complète de cet exemple (toutefois, les parties pertinentes sont affichées ci-dessous).
Les types sont déduites de la SoccerService interface et SoccerResult enum, non indiqué dans votre extrait de code:
L'avantage (de lambdas rapport à la norme anonyme classes) est simplement réduit le niveau de verbosité:
rapport à quelque chose comme:
La différence entre une clôture et une lambda, voir cette question.
Lambda de l'utilisation de la cible de frappe, un peu comme les génériques, les appels de méthode (depuis 1.5) et le diamant [pas] l'opérateur (depuis 1.7). En gros, lorsque le type du résultat applique est dit (ou peut être déduite) qui est utilisée pour fournir le type de la Seule Méthode Abstraite (SAM) type de base et, partant, la méthode des types de paramètres.
Comme un exemple de méthode générique d'inférence en 1.5:
Du diamant et de l'opérateur en 1.7:
Équipe, équipe, équipe, équipe, équipe, équipe. J'ai même l'amour en disant le mot de l'équipe.
Un lambda est une forme limitée de fermeture dans presque exactement de la même manière que les classes internes anonymes, mais avec des différences aléatoires pour attraper vous:
L'extérieur
this
n'est pas caché par un intérieurthis
. Cela signifie que le même texte dans un lambda et un anonyme intérieur de la classe peut signifier subtilement, mais complètement différent choses. Cela devrait garder un Débordement de Pile occupé avec des questions bizarres.Pour compenser le manque d'intérieur
this
, si attribués directement à une variable locale, alors que la valeur est accessible à l'intérieur de la lambda. Autant que je me souvienne (j'ai pu vérifier, mais l'habitude), dans un anonyme intérieur de la classe le local sera portée et masquer les variables à l'extérieur de son champ d'application, mais vous ne pouvez pas l'utiliser. Je crois que le manque d'une instance initialiser cela rend beaucoup plus facile à préciser.Des champs locaux qui n'arrivent pas à être marqué
final
mais qui pourrait l'être, sont traités comme s'ils sontfinal
. Alors ne sont-ils dans le champ d'application, mais vous pouvez réellement lire (mais pas écrire) entre eux.Une plus courte durée de la syntaxe. C'est à ce sujet.
Bien entendu, le reste de la syntaxe Java est tout aussi désespérément mauvais que jamais.
Je ne pense pas que ce soit dans la mise en œuvre initiale, mais au lieu d'être mis en œuvre comme [intérieure] les classes, les lambdas pouvez utiliser la méthode de poignées. La performance de la méthode poignées tombe un peu à court de prévisions antérieures. En faisant disparaître les classes, devrait réduire le bytecode de l'empreinte, éventuellement d'exécution de l'empreinte et certainement la classe de temps de chargement. Il pourrait être une mise en œuvre où la plupart anonymes, les classes internes (pas
Serializable
, trivial statique initialiser) n'est pas passée par le mal conçue classe mécanisme de chargement sans tout particulièrement perceptible incompatibilités.(J'espère que j'ai eu la terminologie wrt cacher correct).