À quoi sert une expression Java 8 Lambda? [dupliquer]
Cette question a déjà une réponse ici:
Considérez l'extrait de code Java 8 suivant.
public static void main(String[] args) {
List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5);
Consumer<Integer> consumer = x -> System.out.print(x);
integers.forEach(consumer);
}
Dans quoi Consumer<Integer> consumer = x -> System.out.print(x)
est-il compilé?
Je comprends que les Lambdas ne sont pas implémentés en tant que classes internes anonymes. Cependant Consumer<Integer>
est une interface donc x -> System.out.print(x)
doit être produire un objet quelconque, mais on ne sait pas quel type d'objet est produit.
Est-il un nouveau type d'objet dans Java 8 pour représenter une expression lambda?
Update Voici le programme décompilé le programme a été respecté avec le complier eclipse java 8 et la sortie ci-dessous provient d'eclipse lorsque vous ouvrez un fichier de classe.
Il semble que l'expression lambda se transforme en une méthode statique sur la classe qui contient le lambda expression private static synthetic void lambda$0(java.lang.Integer x);
// Compiled from Example.java (version 1.8 : 52.0, super bit)
public class Example {
// Method descriptor #6 ()V
// Stack: 1, Locals: 1
public Example();
0 aload_0 [this]
1 invokespecial java.lang.Object() [8]
4 return
Line numbers:
[pc: 0, line: 7]
Local variable table:
[pc: 0, pc: 5] local: this index: 0 type: Example
// Method descriptor #15 ([Ljava/lang/String;)V
// Stack: 4, Locals: 3
public static void main(java.lang.String[] args);
0 iconst_5
1 anewarray java.lang.Integer [16]
4 dup
5 iconst_0
6 iconst_1
7 invokestatic java.lang.Integer.valueOf(int) : java.lang.Integer [18]
10 aastore
11 dup
12 iconst_1
13 iconst_2
14 invokestatic java.lang.Integer.valueOf(int) : java.lang.Integer [18]
17 aastore
18 dup
19 iconst_2
20 iconst_3
21 invokestatic java.lang.Integer.valueOf(int) : java.lang.Integer [18]
24 aastore
25 dup
26 iconst_3
27 iconst_4
28 invokestatic java.lang.Integer.valueOf(int) : java.lang.Integer [18]
31 aastore
32 dup
33 iconst_4
34 iconst_5
35 invokestatic java.lang.Integer.valueOf(int) : java.lang.Integer [18]
38 aastore
39 invokestatic java.util.Arrays.asList(java.lang.Object[]) : java.util.List [22]
42 astore_1 [integers]
43 invokedynamic 0 accept() : java.util.function.Consumer [31]
48 astore_2 [consumer]
49 getstatic java.lang.System.out : java.io.PrintStream [32]
52 aload_2 [consumer]
53 invokevirtual java.lang.Object.getClass() : java.lang.Class [38]
56 invokevirtual java.lang.Class.getCanonicalName() : java.lang.String [42]
59 invokevirtual java.io.PrintStream.println(java.lang.String) : void [48]
62 getstatic java.lang.System.out : java.io.PrintStream [32]
65 aload_2 [consumer]
66 invokevirtual java.lang.Object.getClass() : java.lang.Class [38]
69 invokevirtual java.lang.Class.getTypeName() : java.lang.String [54]
72 invokevirtual java.io.PrintStream.println(java.lang.String) : void [48]
75 aload_1 [integers]
76 aload_2 [consumer]
77 invokeinterface java.util.List.forEach(java.util.function.Consumer) : void [57] [nargs: 2]
82 return
Line numbers:
[pc: 0, line: 10]
[pc: 43, line: 12]
[pc: 49, line: 14]
[pc: 62, line: 15]
[pc: 75, line: 17]
[pc: 82, line: 18]
Local variable table:
[pc: 0, pc: 83] local: args index: 0 type: java.lang.String[]
[pc: 43, pc: 83] local: integers index: 1 type: java.util.List
[pc: 49, pc: 83] local: consumer index: 2 type: java.util.function.Consumer
Local variable type table:
[pc: 43, pc: 83] local: integers index: 1 type: java.util.List<java.lang.Integer>
[pc: 49, pc: 83] local: consumer index: 2 type: java.util.function.Consumer<java.lang.Integer>
// Method descriptor #73 (Ljava/lang/Integer;)V
// Stack: 2, Locals: 1
private static synthetic void lambda$0(java.lang.Integer x);
0 getstatic java.lang.System.out : java.io.PrintStream [32]
3 aload_0 [x]
4 invokevirtual java.io.PrintStream.print(java.lang.Object) : void [74]
7 return
Line numbers:
[pc: 0, line: 12]
Local variable table:
[pc: 0, pc: 8] local: x index: 0 type: java.lang.Integer
Inner classes:
[inner class info: #96 java/lang/invoke/MethodHandles$Lookup, outer class info: #98 java/lang/invoke/MethodHandles
inner name: #100 Lookup, accessflags: 25 public static final]
Bootstrap methods:
0 : # 89 arguments: {#90,#93,#94}
}
1 answers
Le projet actuel de la spécification du langage Java 8 indique (chapitre 15.27.4)
La valeur d'une expression lambda est une référence à une instance d'un classe avec les propriétés suivantes:
- La classe implémente l'interface fonctionnelle ciblée et, si le type cible est un type d'intersection, tous les autres éléments d'interface de l'intersection.
- La classe déclare une méthode qui remplace l'interface fonctionnelle supertype méthodes abstraites (et, potentiellement, d'autres méthodes de son superinterfaces).
- Les types de paramètres de la méthode, le type de retour et les types jetés sont donnés par le type de fonction de l'interface.
- Le corps de la méthode a pour effet d'évaluer le corps lambda, s'il s'agit d'une expression, ou d'exécuter le corps lambda, s'il s'agit d'un bloc; si un résultat est attendu, il est renvoyé par la méthode.
- La classe ne remplace aucune autre méthode de l'interface ou des interfaces mentionné ci - dessus, sauf qu'il peut remplacer les méthodes du
Object
classe.
Notez que le JLS ne dit rien sur la façon dont le code doit être compilé, sauf que le code octet doit prendre en charge la spécification ci-dessus.
En tant que tel, l'objet renvoyé par l'expression lambda
x -> System.out.print(x);
Sera une instance d'une classe qui suit les règles ci-dessus.
, compte tenu de votre commentaire que
consumer.getClass()
Renvoie la classe suivante
Example$$Lambda$1/1072591677
Il il semble qu'il génère une classe de type proxy spécifique aux expressions lambda.
Voir ici: