Je rencontre du code Java comme ceci:
public interface Foo<E> {}
public interface Bar<T> {}
public interface Zar<?> {}
Quelle est la différence entre les trois ci-dessus et comment appellent-ils ce type de déclarations de classe ou d'interface en Java?
Réponses:
Eh bien, il n'y a pas de différence entre les deux premiers - ils utilisent simplement des noms différents pour le paramètre de type (
E
ouT
).La troisième n'est pas une déclaration valide -
?
est utilisée comme un caractère générique qui est utilisé lors de la fourniture d'un argument de type , par exempleList<?> foo = ...
signifie quifoo
fait référence à une liste d'un certain type, mais nous ne savons pas quoi.Tout cela est générique , ce qui est un sujet assez vaste. Vous voudrez peut-être en apprendre davantage à ce sujet à travers les ressources suivantes, bien qu'il y en ait plus bien sûr bien sûr:
la source
T
etE
- ce ne sont que des identifiants. Vous pourriez écrireKeyValuePair<K, V>
par exemple.?
a cependant une signification particulière.C'est plus conventionnel qu'autre chose.
T
est censé être un typeE
est censé être un élément (List<E>
: une liste d'éléments)K
est la clé (en aMap<K,V>
)V
est Value (en tant que valeur de retour ou valeur mappée)Ils sont entièrement interchangeables (nonobstant conflits dans la même déclaration).
la source
Les réponses précédentes expliquent les paramètres de type (T, E, etc.), mais n'expliquent pas le caractère générique, "?", Ou les différences entre eux, donc je vais y répondre.
Tout d'abord, pour être clair: les paramètres génériques et de type ne sont pas les mêmes. Lorsque les paramètres de type définissent une sorte de variable (par exemple, T) qui représente le type d'une étendue, le caractère générique ne le fait pas: le caractère générique définit simplement un ensemble de types autorisés que vous pouvez utiliser pour un type générique. Sans aucune limite (
extends
ousuper
), le caractère générique signifie "utilisez n'importe quel type ici".Le caractère générique vient toujours entre crochets et n'a de sens que dans le contexte d'un type générique:
jamais
ou
Cela devient plus confus là où ils se chevauchent. Par exemple:
Il y a beaucoup de chevauchement dans ce qui est possible avec les définitions de méthode. Les éléments suivants sont, fonctionnellement, identiques:
Donc, s'il y a chevauchement, pourquoi utiliser l'un ou l'autre? Parfois, c'est honnêtement juste du style: certaines personnes disent que si vous n'avez pas besoin d' un paramètre de type, vous devez utiliser un caractère générique juste pour rendre le code plus simple / plus lisible. Une différence principale que j'ai expliquée ci-dessus: les paramètres de type définissent une variable de type (par exemple, T) que vous pouvez utiliser ailleurs dans la portée; pas le caractère générique. Sinon, il existe deux grandes différences entre les paramètres de type et le caractère générique:
Les paramètres de type peuvent avoir plusieurs classes de délimitation; le caractère générique ne peut pas:
Le caractère générique peut avoir des limites inférieures; les paramètres de type ne peuvent pas:
Dans ce qui précède, le
List<? super Integer>
définitInteger
comme une borne inférieure sur le caractère générique, ce qui signifie que le type de liste doit être Integer ou un super-type Integer. La délimitation de type générique est au-delà de ce que je veux couvrir en détail. En bref, il vous permet de définir quels types un type générique peut être. Cela permet de traiter les génériques de manière polymorphe. Par exemple avec:Vous pouvez passer un
List<Integer>
,List<Float>
,List<Byte>
, etc. pournumbers
. Sans délimitation de type, cela ne fonctionnera pas - c'est ainsi que sont les génériques.Enfin, voici une définition de méthode qui utilise le caractère générique pour faire quelque chose que je ne pense pas que vous puissiez faire autrement:
numberSuper
peut être une liste de nombres ou n'importe quel sur-type de nombre (par exemple,List<Object>
), etelem
doit être un nombre ou n'importe quel sous-type. Avec toutes les limites, le compilateur peut être certain que le type.add()
est sûr.la source
Une variable de type, <T>, peut être tout type non primitif que vous spécifiez: tout type de classe, tout type d'interface, tout type de tableau ou même une autre variable de type.
Les noms de paramètres de type les plus couramment utilisés sont:
Dans Java 7, il est permis d'instancier comme ceci:
la source
Les noms de paramètres de type les plus couramment utilisés sont:
Vous verrez ces noms utilisés dans l'API Java SE
la source
le compilateur fera une capture pour chaque caractère générique (par exemple, un point d'interrogation dans la liste) quand il crée une fonction comme:
Cependant, un type générique comme V serait correct et en ferait une méthode générique :
la source