Il s'agit d'un petit extrait de code extrait de certains des exemples qui accompagnent l'analyseur Stanford. Je développe en Java depuis environ 4 ans, mais je n'ai jamais eu une très bonne compréhension de ce que ce style de code est censé indiquer.
List<? extends HasWord> wordList = toke.tokenize();
Je ne m'inquiète pas des détails du code. Ce qui m'embrouille, c'est exactement ce que l'expression générique est censée transmettre, en anglais.
Quelqu'un peut m'expliquer cela?
Réponses:
signifie "Une classe / interface qui s'étend
HasWord
." En d'autres termes,HasWord
lui - même ou l'un de ses enfants ... essentiellement tout ce qui fonctionnerait avecinstanceof HasWord
plusnull
.En termes plus techniques, il
? extends HasWord
s'agit d'un caractère générique délimité, couvert au point 31 de la version Java effective 3e , à partir de la page 139. Le même chapitre de la 2e édition est disponible en ligne au format PDF ; la partie sur les caractères génériques délimités est le point 28 à partir de la page 134.Mise à jour: le lien PDF a été mis à jour depuis que Oracle l'a supprimé il y a quelque temps. Il pointe maintenant vers la copie hébergée par la School of Electronic Engineering and Computer Science de l'Université Queen Mary de Londres.
Mise à jour 2: permet d'entrer dans un peu plus de détails sur les raisons pour lesquelles vous souhaitez utiliser des caractères génériques.
Si vous déclarez une méthode dont la signature s'attend à ce que vous passiez
List<HasWord>
, alors la seule chose que vous pouvez transmettre est aList<HasWord>
.Cependant, si cette signature l'était,
List<? extends HasWord>
vous pourriez passer un à laList<ChildOfHasWord>
place.Notez qu'il existe une différence subtile entre
List<? extends HasWord>
etList<? super HasWord>
. Comme l'a dit Joshua Bloch: PECS = producteur-étend, consommateur-super.Cela signifie que si vous transmettez une collection à partir de laquelle votre méthode extrait des données (c'est-à-dire que la collection produit des éléments pour votre méthode), vous devez utiliser
extends
. Si vous transmettez une collection à laquelle votre méthode ajoute des données (c'est-à-dire que la collection consomme des éléments créés par votre méthode), elle doit utilisersuper
.Cela peut sembler déroutant. Cependant, vous pouvez le voir dans
List
lasort
commande de (qui n'est qu'un raccourci vers la version à deux arguments de Collections.sort). Au lieu de prendre unComparator<T>
, il faut en fait unComparator<? super T>
. Dans ce cas, le comparateur consomme les éléments deList
afin de réorganiser la liste elle-même.la source
List<HasWord>
est exactement ce que vous décrivez: une liste qui contient tous les objetsx
pour lesquelsx instanceof HasWord
renvoie vrai, etnull
. Vous n'avez pas besoin d'un caractère générique pour cela. Le caractère générique signifie qu'il peut également s'agir d'une liste d'un autre type, tant que ce type est un sous-type deHasWord
. (Désolé pour le commentaire tardif.)Un point d'interrogation est un signifiant pour «tout type».
?
seul signifiealors que votre exemple ci-dessus signifie
la source
public Set<Class<?>> getClasses()
signifie? Quelle est la différence avecSet<Class>
? Je regardejavax.ws.rs.core.Application
.List<? extends HasWord>
accepte toutes les classes concrètes qui étendent HasWord. Si vous avez les cours suivants ...... le
wordList
peut contenir UNIQUEMENT une liste de As ou Bs ou un mélange des deux parce que les deux classes étendent le même parent ounull
(ce qui échoue lors de la vérification des instancesHasWorld
).la source
List<? extends Collection<String>> list = new ArrayList<List<String>>();
.List<HasWord>
fait aussi bien pour cela. Le point ici est que cette variable peut contenir unList<A>
ouList<B>
ainsi qu'un aList<HasWord>
.Peut-être qu'un exemple artificiel de "monde réel" aiderait.
Sur mon lieu de travail, nous avons des poubelles qui se déclinent en différentes saveurs. Tous les bacs contiennent des déchets, mais certains bacs sont spécialisés et ne prennent pas tous les types de déchets. Nous avons donc
Bin<CupRubbish>
etBin<RecylcableRubbish>
. Le système de type doit s'assurer que je ne peux pas mettre monHalfEatenSandwichRubbish
dans l'un de ces types, mais il peut aller dans une poubelle généraleBin<Rubbish>
. Si je voulais parler de l'unBin
d'entre euxRubbish
qui pourrait être spécialisé pour que je ne puisse pas jeter des ordures incompatibles, ce serait le casBin<? extends Rubbish>
.(Remarque:
? extends
ne signifie pas en lecture seule. Par exemple, je peux avec des précautions appropriées sortir un morceau de détritus d'une poubelle de spécialité inconnue et le remettre plus tard dans un endroit différent.)Je ne sais pas combien cela aide. Pointeur vers pointeur en présence de polymorphisme n'est pas entièrement évident.
la source
En anglais:
En général, les
?
termes génériques désignent n'importe quelle classe. Et leextends SomeClass
spécifie que cet objet doit s'étendreSomeClass
(ou être cette classe).la source
Le point d'interrogation est utilisé pour définir des caractères génériques . Consultez la documentation Oracle à leur sujet: http://docs.oracle.com/javase/tutorial/java/generics/wildcards.html
la source