tout d'abord, vous ne devriez pas confondre les paramètres de type générique avec la mutabilité. Avoir un caractère générique dans un type d'élément de » List
ne pas empêcher des modifications, il ne impose quelques pratiques restrictions à ce que vous pouvez faire avec le lis t. Avoir une liste déclarée comme List<? extends Number>
implique que la liste référencée a un type d'élément réel de Number
ou une sous-classe de Number
, par exemple, . ce pourrait être un List<Integer>
ou List<Double>
. Vous ne pouvez donc pas ajouter une instance arbitraire Number
car vous ne pouvez pas savoir si elle est compatible avec le type d'élément réel.
Mais vous pouvez toujours ajouter null
, car la référence null
est connue pour être compatible avec tous les types de référence. En outre, vous pouvez toujours supprimer des éléments d'une liste, par ex. appelez remove
ou clear
sans problèmes. Vous pouvez également appeler des méthodes comme Collections.swap(list, index1, index2)
, ce qui est intéressant car il ne serait pas légal d'appeler list.set(index1, list.get(index2))
en raison de règles formelles concernant les types génériques, mais en passant la liste à une autre méthode qui pourrait utiliser une variable de type non générique pour représenter l'élément de la liste type travaux. C'est évidemment correct, car il ne fait que définir des éléments issus de la même liste, qui doit être compatible.
De même, si vous avez un Comparator<Number>
, vous pouvez appeler Collections.sort(list, comparator)
, en tant que comparateur qui peut gérer des nombres arbitraires, il sera capable de gérer tous les nombres qui sont réellement stockés dans la liste.Pour résumer, ayant ? extends
dans le type d'élément d'une collection, et non empêche les modifications.
Comme dit, vous ne pouvez pas insérer de nouveaux éléments arbitraires dans une liste dont le type élément réel pourrait être une sous-classe inconnue de la limite, comme avec List<? extends Number>
. Mais vous avez la garantie d'obtenir une instance Number
lors de la récupération d'un élément, car chaque instance de sous-type Number
est également une instance de Number
. Lorsque vous déclarez List<? super Number>
, son type d'élément réel peut être Number
ou un super type de Number
, par ex. Object
ou Serializable
. Vous pouvez insérer des instances arbitraires Number
, comme vous le savez, il sera compatible avec tout type d'élément réel de la liste, car il s'agit d'un super type de nombre. Lorsque vous récupérez une instance, vous savez seulement qu'il s'agit d'une instance de Object
, car il s'agit du super type de toutes les instances. Pour comparer avec le cas ? extends
, avoir une déclaration ? super
n'empêche pas la lecture, cela impose seulement quelques limitations pratiques. Et de même, vous pouvez toujours le passer à Collections.swap
, car, peu importe le peu que nous savons sur le type réel, l'insertion de ce que nous venons de récupérer de la même liste, fonctionne.
Dans votre deuxième question, vous confondez les côtés. Vous ne regardez pas maintenant la mise en œuvre de min
, mais à l'appelant . La déclaration de min(Comparator<? super T> c)
permet à l'appelant de passer tout comparateur paramétré avec T
ou un super type de T
. Donc, quand vous avez un Stream<String>
, il est valide de passer un Comparator<String>
à la méthode min
, ce qui est exactement ce que vous implémentez via l'expression lambda (s1, s2) -> s1.length()—s2.length()
(cependant, je préférerais Comparator.comparingInt(String::length)
).
Dans l'implémentation de min
, il n'y a en effet aucune connaissance de ce que soit T
ou l'argument de type réel du Comparator
. Mais il suffit de savoir que n'importe quel élément de flux de type T
peut être passé à la méthode compare
du comparateur, qui peut s'attendre à T
ou à un super type de T
.
Cela semble être deux questions différentes. Et en ce qui concerne la première hypothèse, lorsque le compilateur empêche l'ajout à la liste, il ne signifie pas que la liste est immuable. Le compilateur obéit simplement aux règles de vérification de type statique du langage. – manouti
De même, 'List' n'a pas de méthode' longValue() '. – manouti
Salut AR.3 merci pour les commentaires. J'ai changé la question comme vous aviez raison, je vérifiais une méthode de liste au lieu du contenu. Ce sont en effet deux questions différentes, je voulais juste expliquer l'origine de la question. Je comprends ce que vous dites sur immutable, mais maintenant il est logiquement immuable que le compilateur ne vous laissera pas ajouter à la liste. Avez-vous des réponses à ces questions maintenant? –