Quelle est la différence entre <?> Et <? étend Object> dans Java Generics?

94

J'ai déjà vu le joker utilisé pour désigner n'importe quel objet - mais j'ai récemment vu une utilisation de:

<? extends Object>

Puisque tous les objets étendent Object, ces deux usages sont-ils synonymes?

poisson-globe
la source
2
C'est la même chose. Voir stackoverflow.com/questions/2274720/…
Dan
3
@Dan Si vous recherchez "? Extend Object" dans cette question, vous ne trouvez rien. Je lis les réponses pour voir si je peux déduire quoi que ce soit, mais je ne pense pas que ce soit ça. Plus précisément, il ne s'agit pas de génériques.
orbfish
@Dan - C'est une question différente. J'ai déjà vu cette question et je me souviens au moins d'une mention d'une différence subtile. Voyons si je peux le trouver ..
Paul Bellora
Ce n'est pas non plus celui-ci si vous le trouvez: stackoverflow.com/questions/678822/…
orbfish
1
On y va: duplication possible de jokers Unbounded en Java (avec une réponse incorrecte de Kevin Bourrillion pas moins.)
Paul Bellora

Réponses:

103

<?>et <? extends Object>sont également, comme vous vous en doutez.

Il y a quelques cas avec des génériques où ce extends Objectn'est pas réellement redondant. Par exemple, <T extends Object & Foo>fera Tdevenir Objectsous effacement, alors qu'avec <T extends Foo>elle deviendra Foosous effacement. (Cela peut être important si vous essayez de conserver la compatibilité avec une API pré-générique utilisée Object.)

Source: http://download.oracle.com/javase/tutorial/extra/generics/convert.html ; il explique pourquoi la java.util.Collectionsclasse du JDK a une méthode avec cette signature:

public static <T extends Object & Comparable<? super T>> T max(
    Collection<? extends T> coll
)
Ruakh
la source
4
Je ne sais pas comment cet exemple se rapporte? (car il n'utilise ni <?> ni <?
extend
27
@orbfish: Il se rapporte seulement que je pensais que vous trouveriez intéressant, car il est un exemple où en extends Objectfait est significatif. Si je me suis trompé, je m'excuse. J'espère que cela intéressera au moins d'autres personnes qui rencontreront votre question.
ruakh
@ruakh - Était intéressé par les caractères génériques délimités plutôt que par les paramètres de type, mais au moins, vous avez répondu.
orbfish
1
Vous devriez avoir déclaré cela dans votre message d'origine alors. De cette façon, sa réponse aurait pu être plus pertinente pour vous.
liltitus27
19

Bien que ce <?>soit censé être un raccourci pour <? extend object>, il existe une petite différence entre les deux. <?>est réifiable alors que <? extend object>ne l'est pas. La raison pour laquelle ils l'ont fait est de faciliter la distinction du type réifiable. Tout ce qui ressemble <? extends something>, <T>, <Integer>sont nonreifiable.

Par exemple, ce code fonctionnerait

List aList = new ArrayList<>();
boolean instanceTest = aList instanceof List<?>;

mais cela donne une erreur

List aList = new ArrayList<>();
boolean instancetest = aList instanceof List<? extends Object>;

pour plus d'informations, lisez les génériques Java et les collections de Maurice Naftalin

Renzhentaxi Baerde
la source
Comment List <?> Peut-il être réifiable si le compilateur le traduit en List <Object> afin d'obtenir des informations sur le type de? est perdu?
Trismegistos
Ce que je crois <?> Est plus conçu pour une compatibilité descendante avec les API héritées. distinguer avec <Objet> et <? étend Object> qui sont du code post Java 5.
Dennis C
9

<?>est un raccourci pour <? extends Object>. Vous pouvez lire le lien partagé ci-dessous pour plus de détails.


<?>

"?"désigne tout type inconnu, il peut représenter n'importe quel type dans le code pour. Utilisez ce caractère générique si vous n'êtes pas sûr du type.

ArrayList<?> unknownList = new ArrayList<Number>(); //can accept of type Number
unknownList = new ArrayList<Float>(); //Float is of type Number

Remarque: <?> signifie n'importe quoi. Il peut donc accepter des types qui ne sont pas hérités de la Objectclasse.

<? extends Object>

<? extends Object>signifie que vous pouvez passer un objet ou une sous-classe qui étend la Objectclasse.

ArrayList<? extends Number> numberList = new ArrayList<Number>(); //Number of subclass
numberList = new ArrayList<Integer>(); //Integer extends Number
numberList = new ArrayList<Float>(); // Float extends Number 

entrez la description de l'image ici

T - utilisé pour désigner le type
E - utilisé pour désigner l'élément
K - clés
V - valeurs
N - pour les nombres
Réf:

entrez la description de l'image ici

roottraveller
la source
"Il peut donc accepter des types qui ne sont pas hérités de la classe Object", mais toutes les classes Java sont héritées ou implicitement héritées de la Objectclasse.
hackjutsu