En lisant sur la spécification Java-8, je continue de voir des références aux «types SAM». Je n'ai pas été en mesure de trouver une explication claire de ce que c'est.
Qu'est-ce qu'un type SAM et quel est un exemple de scénario dans lequel on pourrait en utiliser un?
Réponses:
Pour résumer le lien Jon publié 1 dans le cas où il ne va jamais vers le bas, « SAM » signifie « méthode abstraite unique » et « SAM type » fait référence à des interfaces comme
Runnable
,Callable
, etc. expressions Lambda, une nouvelle fonctionnalité en Java 8, sont considéré comme un type SAM et peut être librement converti en eux.Par exemple, avec une interface comme celle-ci:
Vous pouvez déclarer une
Callable
utilisation d'expressions lambda comme ceci:Les expressions lambda dans ce contexte ne sont pour la plupart que du sucre syntaxique. Ils ont une meilleure apparence dans le code que les classes anonymes et sont moins restrictifs sur la dénomination des méthodes. Prenez cet exemple sur le lien:
Cela crée une
Comparator
utilisation d'une méthode spécifique qui ne partage pas le même nom queComparator.compare
, de cette façon, vous n'avez pas à suivre la dénomination de l'interface des méthodes et vous pouvez avoir plusieurs remplacements de comparaison dans une classe, puis créer les comparateurs à la volée via les expressions lambda.Aller plus loin ...
À un niveau plus profond, Java les implémente en utilisant l'
invokedynamic
instruction bytecode ajoutée dans Java 7. J'ai dit plus tôt que déclarer un Lambda crée une instanceCallable
ouComparable
similaire à une classe anonyme, mais ce n'est pas strictement vrai. Au lieu de cela, la première fois que leinvokedynamic
est appelé, il crée un gestionnaire de fonction Lambda à l'aide de laLambdaMetafactory.metafactory
méthode , puis utilise cette instance mise en cache dans les futurs appels de Lambda. Plus d'informations peuvent être trouvées dans cette réponse .Cette approche est complexe et inclut même du code qui peut lire des valeurs primitives et des références directement à partir de la mémoire de la pile pour passer dans votre code Lambda (par exemple pour contourner le besoin d'allouer un
Object[]
tableau pour appeler votre Lambda), mais elle permet de futures itérations de l'implémentation Lambda pour remplacer les anciennes implémentations sans avoir à se soucier de la compatibilité du bytecode. Si les ingénieurs d'Oracle modifient l'implémentation Lambda sous-jacente dans une version plus récente de la JVM, Lambdas compilé sur une ancienne JVM utilisera automatiquement l'implémentation la plus récente sans aucune modification de la part du développeur.1 La syntaxe du lien est obsolète. Jetez un œil à la piste Java des expressions Lambda pour voir la syntaxe actuelle.
la source