Caractères génériques multiples sur les méthodes génériques : un casse-tête du compilateur Java
Introduction
Dans les génériques Java , les caractères génériques (*) représentent des types inconnus. Lorsque plusieurs caractères génériques sont utilisés sur des méthodes génériques, cela peut entraîner une confusion et un comportement inattendu. Cet article examine la complexité de plusieurs caractères génériques et leur impact sur la sécurité des types de Java.
La confusion
Considérez le code suivant :
public class TwoListsOfUnknowns { static void doNothing(List<?> list1, List<?> list2) { } public static void main(String[] args) { List<String> list1 = null; List<Integer> list2 = null; doNothing(list1, list2); // compiles fine! } }
Les deux caractères génériques dans doNothing semblent n'avoir aucun rapport, vous permettant de l'appeler avec un List
static void doSomethingIllegal(List<?> list1, List<?> list2) { list1.addAll(list2); // DOES NOT COMPILE!!! }
Cela suggère que même si list1 et list2 peuvent être de types différents, ils peuvent avoir une connexion qui empêche une utilisation directe.
La confusion des caractères génériques imbriqués
Une enquête plus approfondie révèle que la confusion ne réside pas dans plusieurs caractères génériques, mais dans des caractères imbriqués. caractères génériques :
public class LOLUnknowns1 { static void probablyIllegal(List<List<?>> lol, List<?> list) { lol.add(list); // this compiles!! how come??? } }
Ce code se compile sans erreur, même si la liste peut être d'un type différent de celui des éléments de mdr. Cependant, il est important de noter que ce scénario soulève des questions sur la sécurité des types.
La vérité : la conversion de capture
La confusion vient d'un concept appelé conversion de capture. Il permet à certains caractères génériques de capturer des types spécifiques lorsqu'ils sont utilisés dans des méthodes génériques. C'est pourquoi la variante suivante de probablementIllegal compile :
static void probablyIllegalAgain(List<List<? extends Number>> lol, List<? extends Number> list) { lol.add(list); // compiles fine!!! how come??? }
Ici, le caractère générique dans mdr peut capturer un type qui étend Number, tel que List
Comprendre les caractères génériques imbriqués
La clé à retenir est que plusieurs caractères génériques eux-mêmes ne posent pas de problème. La confusion survient lorsque l'on tente d'utiliser un caractère générique imbriqué pour capturer un type qui n'est pas « compatible » en raison de la variance du type.
Dans le cas de LOLUnknowns1, le caractère générique imbriqué dans List> ne peut pas capturer un type spécifique car la capture ne serait pas sûre pour tous les types d'éléments possibles de mdr. C'est pourquoi la liste peut être de n'importe quel type, entraînant des problèmes potentiels de sécurité des types.
Conclusion
Plusieurs caractères génériques sur les méthodes génériques peuvent prêter à confusion, mais comprendre la conversion de capture et ses limites sont cruciales. Les caractères génériques imbriqués nécessitent un examen attentif pour garantir la sécurité du type. En adhérant à ces principes, vous pouvez naviguer dans les subtilités des génériques Java et écrire du code robuste.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!