Ceci est un petit extrait de code tiré de certains des exemples qui accompagnent l'analyseur Stanford. Je développe en Java depuis environ 4 ans, mais je n’ai jamais vraiment compris 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 me rend confus, c'est ce que l'expression générique est censée exprimer exactement, en anglais.
Quelqu'un peut m'expliquer cela?
? extends HasWord
signifie "Une classe/interface qui étend HasWord
." En d'autres termes, HasWord
lui-même ou l'un de ses enfants ... essentiellement tout ce qui fonctionnerait avec instanceof HasWord
Plus null
.
En termes plus techniques, ? extends HasWord
Est un caractère générique délimité, couvert dans la rubrique 31 de Effective Java 3ème édition , commençant le page 139. Le même chapitre de la 2e édition est disponible en ligne au format PDF ; la partie sur les jokers délimités est le numéro 28 à partir de la page 134.
Mise à jour: le lien PDF a été mis à jour car Oracle l'a supprimé il y a longtemps. Il se réfère maintenant à la copie hébergée par la School of Electronic Engineering and Computer Science de l’Université Queen Mary de Londres.
Mise à jour 2: Voyons un peu plus en détail pourquoi vous souhaitez utiliser des caractères génériques.
Si vous déclarez une méthode dont la signature s'attend à ce que vous transmettiez List<HasWord>
, La seule chose que vous pouvez transmettre est un List<HasWord>
.
Cependant, si ladite signature était List<? extends HasWord>
, Vous pourriez alors passer un List<ChildOfHasWord>
.
Notez qu'il existe une différence subtile entre List<? extends HasWord>
Et List<? super HasWord>
. Comme Joshua Bloch l'a dit: PECS = producteur-rallonge, consommateur-super.
Cela signifie que si vous transmettez une collection dont votre méthode extrait des données (c’est-à-dire que la collection produit des éléments que votre méthode peut utiliser), vous devez utiliser extends
. Si vous transmettez une collection à laquelle votre méthode ajoute des données (c’est-à-dire que la collection utilise des éléments créés par votre méthode), vous devez utiliser super
.
Cela peut sembler déroutant. Cependant, vous pouvez le voir dans la commande de List
sort
(qui n'est qu'un raccourci vers la version à deux arguments de Collections.sort). Au lieu de prendre un Comparator<T>
, Il faut en fait un Comparator<? super T>
. Dans ce cas, le comparateur utilise les éléments de List
afin de réorganiser la liste elle-même.
Un point d'interrogation est un signifiant pour "n'importe quel type". ?
seul signifie
Tout type prolongeant
Object
(y comprisObject
)
alors que votre exemple ci-dessus signifie
Tout type développant ou implémentant
HasWord
(y comprisHasWord
siHasWord
est une classe non abstraite)
List<? extends HasWord>
accepte toutes les classes concrètes qui étend HasWord. Si vous avez les cours suivants ...
public class A extends HasWord { .. }
public class B extends HasWord { .. }
public class C { .. }
public class D extends SomeOtherWord { .. }
... le wordList
ne peut contenir UNIQUEMENT qu'une liste de As ou de Bs ou une combinaison des deux parce que les deux classes étendent le même parent ou null
(ce qui échoue instanceof vérifie HasWorld
).
Peut-être qu'un exemple de "monde réel" artificiel aiderait.
Sur mon lieu de travail, nous avons des poubelles de différentes saveurs. Tous les bacs contiennent des ordures, mais certains bacs sont spécialisés et ne prennent pas tous les types de déchets. Nous avons donc Bin<CupRubbish>
et Bin<RecylcableRubbish>
. Le système de types doit s'assurer que je ne peux pas placer mon HalfEatenSandwichRubbish
dans l'un de ces types, mais il peut aller dans une corbeille générale Bin<Rubbish>
. Si je voulais parler d'un Bin
de Rubbish
qui peut être spécialisé afin que je ne puisse pas mettre des ordures incompatibles, alors ce serait Bin<? extends Rubbish>
.
(Remarque: ? extends
ne signifie pas lecture seule. Par exemple, je peux, avec les précautions appropriées, sortir un déchet d'une poubelle de spécialité inconnue et le remettre plus tard dans un endroit différent.)
Je ne sais pas à quel point ça aide. Le pointeur à pointeur en présence de polymorphisme n'est pas tout à fait évident.
En anglais:
C'est un
List
d'un type quelconque qui étend la classeHasWord
, y comprisHasWord
En général, le ?
par générique, n’importe quelle classe. Et le extends SomeClass
spécifie que cet objet doit être étendu SomeClass
(ou être cette classe).
Le point d'interrogation sert à définir des caractères génériques . Consultez la documentation Oracle à leur sujet: http://docs.Oracle.com/javase/tutorial/Java/generics/wildcards.html