Hors le fait que ça nous donne des magnifiques oneliners, on y croise une quantité particulièrement épique de génériques
Malheureusement, quand on le sépare en petits morceaux, nous voyons apparaître des tonnes de génériques.
La bonne nouvelle, c’est que ça s’est amélioré. La dernière fois que j’ai donné cette conférence, ça ressemblait plutôt à ça
L’API était nettement plus complexe et il restait certains problèmes d’inférence
L’inférence, c’est le fait de deviner le type. Comme dans le Collectors ici. On en avait un peu depuis l’arrivé des génériques et il y en a maintenant beaucoup plus avec les lambda
Et vous terminez, pas trop fier de vous et pas trop sûr d’avoir compris le problème avec un aborable SuppressWarning.
Cette session a pour but de vous faire comprendre
1- Pourquoi vous avez ces erreurs
2- Pourquoi c’est fait comme ça
3- Comment c’est implémenté
Et vous terminez, pas trop fier de vous et pas trop sûr d’avoir compris le problème avec un aborable SuppressWarning.
Cette session a pour but de vous faire comprendre
1- Pourquoi vous avez ces erreurs
2- Pourquoi c’est fait comme ça
3- Comment c’est implémenté
Et vous terminez, pas trop fier de vous et pas trop sûr d’avoir compris le problème avec un aborable SuppressWarning.
Cette session a pour but de vous faire comprendre
1- Pourquoi vous avez ces erreurs
2- Pourquoi c’est fait comme ça
3- Comment c’est implémenté
Et vous terminez, pas trop fier de vous et pas trop sûr d’avoir compris le problème avec un aborable SuppressWarning.
Cette session a pour but de vous faire comprendre
1- Pourquoi vous avez ces erreurs
2- Pourquoi c’est fait comme ça
3- Comment c’est implémenté
Et vous terminez, pas trop fier de vous et pas trop sûr d’avoir compris le problème avec un aborable SuppressWarning.
Cette session a pour but de vous faire comprendre
1- Pourquoi vous avez ces erreurs
2- Pourquoi c’est fait comme ça
3- Comment c’est implémenté
Et vous terminez, pas trop fier de vous et pas trop sûr d’avoir compris le problème avec un aborable SuppressWarning.
Cette session a pour but de vous faire comprendre
1- Pourquoi vous avez ces erreurs
2- Pourquoi c’est fait comme ça
3- Comment c’est implémenté
Emplit de désespoir vous ne savez pas trop comment vous en débarasser parce que toutes vos tentatives ne compilent pas.
Emplit de désespoir vous ne savez pas trop comment vous en débarasser parce que toutes vos tentatives ne compilent pas.
Et vous terminez, pas trop fier de vous et pas trop sûr d’avoir compris le problème avec un aborable SuppressWarning.
Cette session a pour but de vous faire comprendre
1- Pourquoi vous avez ces erreurs
2- Pourquoi c’est fait comme ça
3- Comment c’est implémenté
Par exemple, les arrays
C’est cette règle qui a forcé plusieurs décisions de design et qui a par conséquent rendu notre ami le @SuppressWarning si fréquent.
On en vient à ce demander comment ils auraient fait si les annotations n’étaient pas apparu au même moment.
Par exemple, les arrays
Les arrays sont covariants. Si on peut assigner un object d’un type donné à un autre type, alors on peut assigner un array d’objet à un array de l’autre type
Par contre pour les génériques on ne peut pas. Il est illégal de faire la ligne du bas.
Car, un code qui compile sans warning ne doit jamais jamais causé un ClassCastException
Un exemple que vous avez sûrement déjà vu pour expliquer pourquoi c’est interdit.
Comme vous voyez, si la covariance était permisse nous briserions la règle #1
Et pour un array
Parce que pour un tableau, on a envie que ça ça passe
On ne peut pas faire de tableau de génériques et c’est bien dommage.
Une seule exception, un tableau de wildcard. Le wildcard étant un type quelconque, nous n’avons pas de soucis.
Dans tous les autres cas c’est interdit pour la raison suivante
On ne peut pas faire de tableau de génériques et c’est bien dommage.
Une seule exception, un tableau de wildcard. Le wildcard étant un type quelconque, nous n’avons pas de soucis.
Dans tous les autres cas c’est interdit pour la raison suivante
Nous avons le cas suivant.
Grâce une asticieuse utilisation de la covariance des arrays, si les arrays génériques étaient permis, nous briserions la règle numéro 1.
En résumé, si les designers des génériques avaient laissé tomber la règle pour ce cas et laisser le bénéfice du doute au développeur, nous aurions échappé à plusieurs complexité.
Je vous laisse juge de leur décision.
Par exemple, les arrays
Une méthode retourne un type en wildcard
Pour garder la cohérence, le compilateur va fixer le type et l’appeler capture#6 pour s’assurer de la cohérence du type donné à T
Pour les développeurs de framework, ne jamais retourner de wildcard si possible
Une méthode retourne un type en wildcard
Pour garder la cohérence, le compilateur va fixer le type et l’appeler capture#6 pour s’assurer de la cohérence du type donné à T
Pour les développeurs de framework, ne jamais retourner de wildcard si possible
Warning mandatory pour ne pas enfreindre la règle #1
Par exemple, les arrays
Lorsqu’il y a un paramètre, le compilateur prend le type du paramètre pour déterminer le type de retour.
Cette pour cette raison que le syntaxe que vous voyez est apparu en Java 5. Le paramètre ne sert à rien sauf à fixer le type.
Mais ça vous les savez sûrement déjà.
Ensuite s’il n’y a pas de paramètre, le compilateur déduit le type à partir de la variable à laquelle elle est assignée.
Mais ça ne marche pas à tous les coups.
Dans les cas d’overloading par exemple. Impossible de deviner quelle méthode doit être appelé
Un truc classique est d’ajouter un paramètre juste pour la bonne cause. C’est un contournement classique.
Dans les cas d’overloading par exemple. Impossible de deviner quelle méthode doit être appelé
Pour les lambda, il est très fort probable d’en avoir besoin.
Vous avez ici l’exemple du début où je l’utilisais. Fort heureusement, ce n’est pas nécessaire dans la nouvelle API.
Par contre, j’ai un peu de difficulté à vous promettre que ce sera toujours le cas. On touche du bois
Par exemple, les arrays
Everybody knows what is erasure?
List<String> and ArrayList<String> got erasure
The variable in the loop kept is type
Boring, nous on va parler des cas où il n’y a pas d’erasure.
Oh dear, no erasure
On récupère la classe parent qui s’avère être générique et implémente donc l’interface ParameterizedType.
Il y a eu un ajout de plusieurs interfaces.
Elles sont passées presque complètement inaperçu mais peuvent être utile.
Par exemple, l’exemple précédent peut servir à faire ça
Par polymorphisme, le getClass() retourne ADao. Donc la superclass est BaseDao, et le type du paramètre générique est A.
And yes, the dumb part if the SuppressWarnings. It comes come the (Class<T>) cast. Since the compiler can’t be sure that actualType is a Class, we get the warning. On ne peut pas s’en débarasser.
Par exemple, les arrays
Vous avez une classe générique étendue par un autre qui fixe le type à String. Rien de plus classique.
Magie, à la décompilation, une nouvelle méthode est apparue. C’est le bridge. Elle ne sert à rien sauf à l’assurer c’est bien une String qui est passé en paramètre.
Le volatile c’est parce que la modificateur de champs et de méthodes ont des codes communs. Donc en fait, le décompilateur (jad) a un petit bogue.
Attention, Java Decompiler ne vous montrera pas le bridge, il le fait disparaitre. On ne le voit qu’avec Jad qui est moins futé.
La règle #1 n’est pas enfreinte car nous avons un warning.
Par contre, Java ajoute dans ce cas particulier une sur-protection.
Impossible de s’en prémunir à la compilation. Tout est valide. Il fallait donc combler la faille pour empêcher un Object d’être assigné à une String et amener le chaos et l’anarchie dans la JVM. D’où, le bridge.
Vous avez deux méthodes. L’une déléguant directement à l’autre.
Si vous avez un framework faisant des proxies dynamiques ou de l’AOP, vous vous retrouvez avec deux méthodes instrumentées. Et c’est assez rare que c’est ce que vous aviez prévus.
Résultat, plus rien ne marche. Par exemple, Spring qui utilise beaucoup de proxies, a dû implémenter une class nommée BridgeMethodResolver qui permet de trouver la méthode concrête appelée par le bridge. Et malheureusement, le JDK n’a pas prévu le coup donc il faut la déduire.
C’est ce que j’avais de plus compliqué à vous montrer aujourd’hui. Passons donc à la conclusion.
J’ai pas mal pataugé sur ces sujets car ils sont assez peu documentés. C’est pas simple mais on finit par s’y retrouver.
La question qui me taraude maintenant c’est “Est-ce que vous connaissiez tout ça?” Pour m’assurez que je ne raconte pas que des banalités.
Est-ce que chaque personne pourrait lever la main et me dire si vous avez appris au moins une chose aujourd’hui?
Maurice Naftalin
Oh dear, no erasure