Java 8 : Un ch'ti peu de lambda
description
Transcript of Java 8 : Un ch'ti peu de lambda
![Page 1: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/1.jpg)
Un ch'ti peu de lambdades lambdas à l'ombre du beffroi
Rémi ForaxDécembre 2012
![Page 2: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/2.jpg)
Moi
MCF à l'université Paris Est Marne-La-Vallée
Joue avec Java depuis trop longtemp pour l'avouer
Créateur de langage dynamique ou pas
Expert pour les JSR 292 (invokedynamic) et JSR 335 (lambda)
Contributeur OpenJDK, ASM, Tatoo, PHP.reboot, JDart, etc...
![Page 3: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/3.jpg)
Les lambdaaaaahs
Pourquoi
par ce que Java c'était trop simple ??
Comment
on va tout casser Java ??
Sous le capot
surtout ne pas toucher à la VM ??
![Page 4: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/4.jpg)
Partie IIntroduction aux lambdas
![Page 5: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/5.jpg)
Dit papa, c'est quoi des lambdas ?
private static ArrayList<File> subDirectories(File directory) { ArrayList<File> directories = new ArrayList<>(); File[] files = directory.listFiles(); for(File file: files) { if (file.isDirectory()) { directories.add(file); } } return directories;}
public static void main(String[] args) { File file = new File("."); for(File dir: subDirectories(file)) { System.out.println(dir); }}
![Page 6: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/6.jpg)
Parties codantes
private static ArrayList<File> subDirectories(File directory) { ArrayList<File> directories = new ArrayList<>(); File[] files = directory.listFiles(); for(File file: files) { if (file.isDirectory()) { directories.add(file); } } return directories;}
public static void main(String[] args) { File file = new File("."); for(File dir: subDirectories(file)) { System.out.println(dir); }}
![Page 7: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/7.jpg)
Seconde version
private static File[] subDirectories(File directory) { return file.listFiles(new FileFilter() { @Override public boolean accept(File path) { return path.isDirectory(); } });}
public static void main(String[] args) { File file = new File("."); for(File dir: subDirectories(file)) { System.out.println(dir); }}
![Page 8: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/8.jpg)
Parties codantes
private static File[] subDirectories(File directory) { return file.listFiles(new FileFilter() { @Override public boolean accept(File path) { return path.isDirectory(); } });}
public static void main(String[] args) { File file = new File("."); for(File dir: subDirectories(file)) { System.out.println(dir); }}
![Page 9: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/9.jpg)
Problème des classes anonymes
Une classe anonyme est pas super adaptée
visuellement
Verbeux, rapport signal/bruit pas satisfaisant
sémantiquement
On veut envoyer une expression, créont une classe ...
performancecréation d'un objet à chaque appel
+1 classe sur le disque
+1 instance de java.lang.Class + métadata en mémoire
![Page 10: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/10.jpg)
Comment font les autres langages ?
Lisp/Clojure closure's
Ruby block
Groovy Closure
Scala/C# lambda
Javascript/Python anonymous function
Python comprehension/C# Linq
Pourquoi introduire les lambdas en Java ?
les classes anonymes couvrent déjà le besoin ??
![Page 11: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/11.jpg)
L'excuse multicore
On a plein de coeurs et on sait pas quoi en faire !
Si une partie du code est transformable en objet
On peut distribuer / paralleliser l'exécution
Presque magique
Enfin, si on a un effet de bord, on est mort !
![Page 12: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/12.jpg)
Sans lambda ...
private static File[] subDirectories(File directory) { return file.listFiles(new FileFilter() { @Override public boolean accept(File path) { return path.isDirectory(); } });}
public static void main(String[] args) { File file = new File("."); for(File dir: subDirectories(file)) { System.out.println(dir); }}
![Page 13: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/13.jpg)
Avec une lambda ...
private static File[] subDirectories(File directory) { FileFilter filter = (File path) -> path.isDirectory(); return file.listFiles(filter);}
public static void main(String[] args) { File file = new File("."); for(File dir: subDirectories(file)) { System.out.println(dir); }}
![Page 14: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/14.jpg)
Syntaxe pour les expressions
sans paramètre
() -> System.out.println("welcome to the land of shtis")
avec un paramètre (inférence)
employee -> employee.isManager()
avec plusieurs paramètres
en déclarant les types
(int x, int y) -> x == y
sans déclarer les types (inférence)
(x, y) -> x == y
![Page 15: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/15.jpg)
Syntaxe pour les instructions
sans paramètre
() -> { System.out.println("welcome to the land of shtis");}
avec un paramètre (inférence)
employee -> { return employee.isManager();}
avec plusieurs paramètres (inférence)
(index1, index2) -> { list.set(index1, list.get(index2));}
![Page 16: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/16.jpg)
Sémantique
Typé par une functional interface (ex SAM)
Runnable, Callable, Filter, Function, ...
Une lambda n'est pas un objet
“this” représente la classe courante pas la lambda
Une lambda est convertissable en un objet qui implante une functional interface
![Page 17: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/17.jpg)
En utilisant l'inférence
private static File[] subDirectories(File directory) { return file.listFiles( path -> path.isDirectory() );}
public static void main(String[] args) { File file = new File("."); for(File dir: subDirectories(file)) { System.out.println(dir); }}
![Page 18: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/18.jpg)
Comment l'inférence marche ?
le compilo regarde le(s) type(s) target(s)
FileFilter filter = path -> path.isDirectory();
l'interface FileFilter est déclarée
interface FileFilter { boolean accept(File file);}
utilise jamais le body de la lambda !
Java != Haskell
![Page 19: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/19.jpg)
Method Reference
private static File[] subDirectories(File directory) { return file.listFiles( File::isDirectory );}
public static void main(String[] args) { File file = new File("."); for(File dir: subDirectories(file)) { System.out.println(dir); }}
![Page 20: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/20.jpg)
Method Reference
Raccourçi si la lambda délègue juste à une méthode
On utilise :: rien que pour embéter les C++eux
Si la méthode est surchargée, l'inférence utilise le target type pour trouver les types des paramétres
![Page 21: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/21.jpg)
Et les collections
Avoir des lambdas c'est bien, mais sans support au niveau des APIs ...
Nouvelle interface java.util.Stream
Sequentielle ou parallele
Operations
intermédiairefilter, map, sorted, distinct, flatMap ...
terminalesreduce, forEach, into, findFirst ...
![Page 22: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/22.jpg)
Full Stream
private static ArrayList<File> subDirectories( File directory) { return Arrays.stream(directory.listFiles()). filter(File::isDirectory). into(new ArrayList<>());}
public static void main(String[] args) { File file = new File("."); for(File dir: subDirectories(file)) { System.out.println(dir); }}
![Page 23: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/23.jpg)
Avec tout dans le main()
La méthode subdirectories() sert pas vraiment !
public static void main(String[] args) { File directory = new File("."); Arrays.stream(directory.listFiles()). filter(File::isDirectory). forEach(dir -> System.out.println(dir));}
![Page 24: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/24.jpg)
Capturer la valeur de variables locales
Et si je veux tous les sous-répertoires dont le nom commence par args[0]
public static void main(String[] args) { File directory = new File("."); String name = args[0]; Arrays.stream(directory.listFiles()). filter(File::isDirectory). filter(dir -> dir.getName().startsWith(name). forEach(dir -> System.out.println(dir));}
Une lambda peut capturer les valeurs des variables locales (comme avec une classe anonyme)
![Page 25: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/25.jpg)
Pipeline d'élements
Arrays.stream(directory.listFiles()). filter(File::isDirectory). filter(dir -> dir.getName().startsWith(name). forEach(dir -> System.out.println(dir));
filter
Arrays.asStream(array)
collection.stream()
iterator.stream()
block
On pousse les élements à travers le pipeline
filter
false false
![Page 26: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/26.jpg)
Method reference sur une instance
Il est possible de créer une méthode réference sur une instance
public static void main(String[] args) { File directory = new File("."); String name = args[0]; Arrays.stream(directory.listFiles()). filter(File::isDirectory). filter(path -> path.getName().startsWith(name). forEach(System.out::println);}
![Page 27: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/27.jpg)
En résumé
Java permet de définir des lambdas et des références sur des méthodes
Une lambda est une expression ou une fonction anonyme que l'on peut convertir en un objet pour envoyer à une méthode
L'API des collections est mis à jour pour supporter les lambdas
![Page 28: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/28.jpg)
Partie IIChangements pour Java
![Page 29: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/29.jpg)
Changements pour Java
Gros problèmes
Inférence déjà existante pas assez puissante
Interface pas extensible
Et des petits +
Effectively finalPlus besoin de déclarer les variables locales utilisée dans les lambdas classes anonymes final
Eviter les garbages classesMettre les méthodes statiques public/private dans les interfaces
![Page 30: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/30.jpg)
Améliorer l'inférence
Java 5/7 infére
les variables de type des méthodesList<String> list =Array.asList("foo", "bar")
List<String> list = Collections.emptyList();
les instantiations de types paramétrésList<String> list = new ArrayList<>();
=> mais f(Collections.emptyList()) marche pas !
![Page 31: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/31.jpg)
Inference avec Java 8
Inference pour les types des lambdas
donc de gauche à droite comme les <>
Inference pour appel de méthode/instantiation diamond (JEP 101)
si dans un appel de méthodefoo(new ArrayList<>()); // ok
avec propagationString s = Collections.emptyList().get(0); // ok
![Page 32: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/32.jpg)
Les demi-dieux de l'inférence
Dan Smith Maurizio Cimadamore
![Page 33: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/33.jpg)
Extensibilité des interfaces
On veux obtenir un Stream à partir d'une Collection
collection.stream()
On ne peut pas ajouter une méthode dans une interface !
Solution académique: traits (!= Scala traits)
![Page 34: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/34.jpg)
Trait
Un type contenant des méthodes abstraites et des méthodes concrètes (mais pas de champs)
Ajouter une méthode si l'on fournit l'implantation ne casse pas la compatibilité
idée: et si on pouvait mettre du code dans une interface
![Page 35: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/35.jpg)
but, you broke Java !
![Page 36: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/36.jpg)
![Page 37: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/37.jpg)
Default method
Permet de fournir un code par défaut qui est utiliser si il n'en n'existe pas
interface Iterator<T> { public boolean hasNext(); public T next();
public default void remove() { throw new UnsupportedOperationException(); }
public default void forEach(Block<? super T> block) { while(hasNext()) { block.accept(it.next()); } }}
![Page 38: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/38.jpg)
Sémantique
La méthode par défaut n'est utilisée que “par défaut”
interface A { default void m() { ... }}
class B implements A{ void m() { ... } // pas besoin de A::m !}
![Page 39: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/39.jpg)
Héritage mutiple ??
interface A { default void m() { ... }}
interface B { default void m() { ... }}
class C implements A, B { // compile pas, faut choisir A::m ou B::m }
![Page 40: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/40.jpg)
Héritage mutiple
interface A { default void m() { ... }}
interface B { default void m() { ... }}
class C implements A, B { // on doit fournir un code pour m() public void m() { A.super.m(); // on appel m de A B.super.m(); // on appel m de B } }
![Page 41: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/41.jpg)
Partie IIIdans les entrailles de la VM
![Page 42: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/42.jpg)
Au menu ...
Comment les méthodes par défaut fonctionnent ?
Comment les lambdas sont compilés ?
Comment les lambdas sont optimisées par la VM ?
![Page 43: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/43.jpg)
Méthode par défaut
Le compilo ne peut rien faire !
Sinon on doit recompiler toutes les libraries
Doit être fait par la VM
mais● les règles de redéfinition (override) dépendent des generics ● Les générics sont un artifact à la compile pas connu à
l'exécution (erasure)
La VM doit savoir lire les signatures des generics
![Page 44: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/44.jpg)
Méthode par défaut et erasure
interface Foo<T> { default T getFoo() { return ...; }}interface Bar { String getFoo();}class A implements Bar, Foo<String> {}
![Page 45: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/45.jpg)
Méthode par défaut et erasure
interface Foo<T> { default ObjectT getFoo() { return ...; }}interface Bar { String getFoo();}class A implements Bar, Foo<String> {}
la VM doit générer deux méthodes Object getFoo() et String getFoo()
![Page 46: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/46.jpg)
Méthode par défaut et erasure
interface Foo<T> { default ObjectT getFoo() { return ...; }}interface Bar { String getFoo();}class A implements Bar, Foo<String> { Object getFoo() { return getFoo(); // appel String getFoo() } String getFoo() { return ...; // recopie le bytecode de Foo::getFoo }}
![Page 47: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/47.jpg)
Compiler une lambda naïvement
On créé une méthode synthetic pour le corps de la lambda
On crée une classe anonyme lors de la convertion vers la functional interface
iterator.forEach(dir -> System.out.println(dir));
devient
iterator.forEach(new Block<File>() { public void accept(File dir) { return lambda$1(dir); }});
static void lambda$1(File dir) { System.out.println(dir);}
![Page 48: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/48.jpg)
Lambda objet constant ?
A l'exécution, il y a deux sortes de lambdas
Les lambdas qui ne captures pas de variable ou les méthodes référence sur une classe
● path -> path.isDirectory● File::isDirectory
Celles qui capture des variables ou les méthode référence sur des instances
● path -> path.getName().startsWith(args[0)● System.out::println
![Page 49: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/49.jpg)
Compiler vers une classe anonyme ?
Et on se récupère tous les problèmes de perf des classes anonymes
De plus, si une lambda ne capture pas de variable, on pourrait au moins la crée que une seule fois
Mais si on utilise un champ static final, l'initialisation à lieu même si on ne l'utilise pas
![Page 50: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/50.jpg)
Invokedynamic to rule them all
On veut un mécanisme qui délai l'initialisation au premier accès
invokedynamic
On veut un mécanisme qui permet d'indiquer que le résultat d'un calcul est constant
invokedynamic
On veut un pointeur de fonction pour éviter la création des classe anonymes
java.lang.invoke.MethodHandle
![Page 51: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/51.jpg)
Compiler une lambda
iterator.forEach(dir -> System.out.println(dir));
devient
iterator.forEach(invokedynamic bootstrap [lambda$1]);
static void lambda$1(File dir) { System.out.println(dir);}CallSite bootstrap(Lookup lookup, String name, MethodType type, MethodHandle mh) { if (type.parameterCount() == 0) { return new ConstantCallSite(proxy(mh)); } return ...}
![Page 52: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/52.jpg)
Lambda Proxy
Instance d'une classe qui contient le pointeur de fonction (MethodHandle) vers la lambda à exécuter
Il n'y a besoin que d'une classe proxy par functional interface
Le proxy est généré dynamiquement par la VM,pas forcément besoin de bytecode associé
![Page 53: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/53.jpg)
Lambda Proxy en pseudo code
Le code Java correspondant est à peu près :
public class Proxy$Block implements Block { private final @Stable MethodHandle mh;
public void accept(Object o) { mh.invokeExact(o); }}
invokeExact() est un pointer check + un appel à un pointeur de fonction
![Page 54: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/54.jpg)
Optimizations lors de l'appel
Avoir 1 seul classe pour 1 interface permet à la VM de remplacer l'appel à l'interface par le code de la classe(Class Hierarchy Analysis)
interface Iterator<T> { ... public default void forEach(Block<? super T> block) { while(hasNext()) { block.accept(it.next()); } }}
ici, block est toujours une instance de Proxy$Block
![Page 55: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/55.jpg)
Optimizations lors de l'appel
Si un objet constant dans une boucle, il est sortie de la boucle
interface Iterator<T> { ... public default void forEach(Block<? super T> block) { while(hasNext()) { mh.invokeExact(it.next()); } }}
Dans le cas d'un method handle, il faut inliner le code référencé par le pointer de fonction (fairy tale mode)
![Page 56: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/56.jpg)
dans le monde merveilleuxdes licornes
On guarde la boucle avec un test sur le method handle(comme pour l'On Stack Replacement)
interface Iterator<T> { ... public default void forEach(Block<? super T> block) { if (block.mh == lambda$1) { while(hasNext()) { System.out.println(it.next()); } } else deopt(); }}
et comme block est pris en paramètre, l'idée est de spécialiser le code à l'endroit de l'appel ce qui permet de ne pas faire le test
![Page 57: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/57.jpg)
Le léger hic
Le code de la VM qui crée le lambda proxy et qui l'optimise est pas prêt
Le plan est prêt depuis longtemps, c'est la réalisation qui prend du temps
On doit quand même livrer un truc pour le JDK8
Solution temporaire: la méthode de bootstrap génère une classe anonyme dynamiquement en utilisant ASM
On implantera les lambda proxies dans une update du jdk8
![Page 58: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/58.jpg)
En résumé
La première version des lambdas sera pas la plus optimisée
L'API dans java.util doit être fini pour fin janvier
La spec de l'inférence pas fini même si ça se précise
Bref on est grâve à la bourre
![Page 59: Java 8 : Un ch'ti peu de lambda](https://reader034.fdocuments.fr/reader034/viewer/2022052303/555c26c4d8b42a0b418b4d57/html5/thumbnails/59.jpg)
Si vous avez du temps libre
et même si vous n'en avez pas !
Downloader la dernière version du jdk8 avec les lambdas
http://jdk8.java.net/lambda/
Tester l'API, jouer avec, remonter tous les bugs