J'utilise Eclipse pour m'aider à nettoyer du code afin d'utiliser correctement les génériques Java. La plupart du temps, il fait un excellent travail d'inférence de types, mais il existe certains cas où le type inféré doit être aussi générique que possible: Object. Mais Eclipse semble me donner la possibilité de choisir entre un type d'objet et un type de «?».
Alors, quelle est la différence entre:
HashMap<String, ?> hash1;
et
HashMap<String, Object> hash2;
Réponses:
Une instance de
HashMap<String, String>
correspondancesMap<String, ?>
mais pasMap<String, Object>
. Supposons que vous souhaitiez écrire une méthode qui accepte les mappages deString
s à n'importe quoi: si vous voulez écrirevous ne pouvez pas fournir un fichier
HashMap<String, String>
. Si vous écrivezÇa marche!
Une chose parfois mal comprise dans les génériques de Java est que ce
List<String>
n'est pas un sous-type deList<Object>
. (MaisString[]
c'est en fait un sous-type deObject[]
, c'est l'une des raisons pour lesquelles les génériques et les tableaux ne se mélangent pas bien (les tableaux en Java sont covariants, les génériques ne le sont pas, ils sont invariants )).Exemple: si vous souhaitez écrire une méthode qui accepte les
List
s deInputStream
s et les sous-types deInputStream
, vous écririezÀ propos: Effective Java de Joshua Bloch est une excellente ressource lorsque vous souhaitez comprendre les choses pas si simples de Java. (Votre question ci-dessus est également très bien traitée dans le livre.)
la source
Une autre façon de penser à ce problème est que
est équivalent à
Associez ces connaissances au "Principe Get and Put" dans la section (2.4) de Java Generics and Collections :
et le joker pourrait commencer à avoir plus de sens, espérons-le.
la source
HashMap<String, ? extends Object>
donc il empêche seulementnull
d'être ajouté dans le hashmap?Il est facile de comprendre si vous vous souvenez qu'il
Collection<Object>
s'agit simplement d'une collection générique qui contient des objets de typeObject
, maisCollection<?>
est un super type de tous les types de collections.la source
Les réponses ci-dessus sur la covariance couvrent la plupart des cas mais manquent une chose:
"?" inclut "Object" dans la hiérarchie des classes. Vous pourriez dire que String est un type d'Objet et Object est un type de?. Tout ne correspond pas à Object, mais tout correspond à?.
la source
Vous ne pouvez rien insérer en toute sécurité
Map<String, ?>
, car vous ne savez pas de quel type les valeurs sont censées être.Vous pouvez placer n'importe quel objet dans a
Map<String, Object>
, car la valeur est connue pour être unObject
.la source
Map<String,Integer>
. Seuls lesInteger
objets doivent être stockés dans la carte en tant que valeurs. Mais puisque vous ne connaissez pas le type de la valeur (il est?
), vous ne savez pas si s'il est sûr d'appelerput(key, "x")
,put(key, 0)
ou quoi que ce soit d' autre.Déclarer en
hash1
tant queHashMap<String, ?>
dicte que la variablehash1
peut contenir tout ceHashMap
qui a une clé deString
et tout type de valeur.Tout ce qui précède est valide, car la variable
map
peut stocker n'importe laquelle de ces cartes de hachage. Cette variable ne se soucie pas du type de valeur, du hashmap qu'il contient.Cependant, le fait d'avoir un caractère générique ne vous permet pas de placer n'importe quel type d'objet dans votre carte. en fait, avec la carte de hachage ci-dessus, vous ne pouvez rien y mettre en utilisant la
map
variable:Tous les appels de méthode ci-dessus entraîneront une erreur de compilation car Java ne sait pas quel est le type de valeur du HashMap à l'intérieur
map
.Vous pouvez toujours obtenir une valeur de la carte de hachage. Bien que vous «ne connaissiez pas le type de la valeur» (parce que vous ne savez pas quel type de carte de hachage se trouve dans votre variable), vous pouvez dire que tout est une sous-classe de
Object
et, par conséquent, tout ce que vous obtenez de la carte sera du type Object:Le bloc de code ci-dessus imprimera 10 sur la console.
Donc, pour finir, utilisez un
HashMap
avec des jokers lorsque vous ne vous souciez pas (c'est-à-dire que peu importe) quels sont les types deHashMap
, par exemple:Sinon, spécifiez les types dont vous avez besoin:
Dans la méthode ci-dessus, nous aurions besoin de savoir que la clé de la carte est a
Character
, sinon nous ne saurions pas quel type utiliser pour en obtenir des valeurs.toString()
Cependant, tous les objets ont une méthode, de sorte que la carte peut avoir n'importe quel type d'objet pour ses valeurs. Nous pouvons toujours imprimer les valeurs.la source