Ich verwende Eclipse, um Code zu bereinigen und Java-Generika ordnungsgemäß zu verwenden. Meistens leistet es hervorragende Arbeit, Typen abzuleiten, aber es gibt einige Fälle, in denen der abgeleitete Typ so allgemein wie möglich sein muss: Objekt. Aber Eclipse scheint mir die Möglichkeit zu geben, zwischen einem Objekttyp und einem '?' Typ zu wählen.
Was ist der Unterschied zwischen:
HashMap<String, ?> hash1;
und
HashMap<String, Object> hash2;
Antworten:
Eine Instanz von
HashMap<String, String>
Übereinstimmungen,Map<String, ?>
aber nichtMap<String, Object>
. Angenommen, Sie möchten eine Methode schreiben, die Karten vonString
s zu irgendetwas akzeptiert : Wenn Sie schreiben würdenSie können keine liefern
HashMap<String, String>
. Wenn du schreibstEs klappt!
Eine Sache, die in Javas Generika manchmal missverstanden wird,
List<String>
ist, dass es sich nicht um einen Subtyp von handeltList<Object>
. (AberString[]
ist in der Tat ein Subtyp vonObject[]
, das ist einer der Gründe, warum Generika und Arrays nicht gut mischen. (Arrays in Java sind kovariant, Generika sind nicht, sie sind invariant )).Beispiel: Wenn Sie eine Methode schreiben möchten, die
List
s vonInputStream
s und Untertypen von akzeptiertInputStream
, würden Sie schreibenÜbrigens: Joshua Blochs effektives Java ist eine hervorragende Ressource, wenn Sie die nicht so einfachen Dinge in Java verstehen möchten. (Ihre Frage oben wird auch im Buch sehr gut behandelt.)
quelle
Eine andere Möglichkeit, über dieses Problem nachzudenken, ist die folgende
ist äquivalent zu
Koppeln Sie dieses Wissen mit dem "Get and Put-Prinzip" in Abschnitt (2.4) von Java Generics and Collections :
und der Platzhalter macht hoffentlich mehr Sinn.
quelle
HashMap<String, ? extends Object>
so verhindert es nurnull
, in die Hashmap hinzugefügt zu werden?Es ist leicht zu verstehen, wenn Sie sich daran erinnern, dass dies
Collection<Object>
nur eine generische Sammlung ist, die Objekte vom Typ enthältObject
, aberCollection<?>
ein Supertyp aller Arten von Sammlungen ist.quelle
Die Antworten über der Kovarianz decken die meisten Fälle ab, übersehen jedoch eines:
"?" schließt "Objekt" in die Klassenhierarchie ein. Man könnte sagen, dass String eine Art von Objekt ist und Object eine Art von? Nicht alles passt zum Objekt, aber alles passt?
quelle
Sie können nichts sicher eingeben
Map<String, ?>
, da Sie nicht wissen, welchen Typ die Werte haben sollen.Sie können jedes Objekt in ein Objekt einfügen
Map<String, Object>
, da der Wert als bekannt istObject
.quelle
Map<String,Integer>
. NurInteger
Objekte sollten als Werte in der Karte gespeichert werden. Aber da Sie den Typ des Wertes nicht wissen (es ist?
), weiß man nicht , ob , wenn es sicher ist zu nennenput(key, "x")
,put(key, 0)
oder irgendetwas anderes.Das Deklarieren
hash1
alsHashMap<String, ?>
diktiert, dass die Variablehash1
jeden enthalten kannHashMap
, der einen SchlüsselString
und einen beliebigen Werttyp hat.Alle oben genannten Punkte sind gültig, da die Variable
map
jede dieser Hash-Maps speichern kann. Dieser Variablen ist es egal, um welchen Werttyp es sich bei der darin enthaltenen Hashmap handelt.Hat eine Wildcard Having nicht aber lassen Sie jede Art von Objekt in Ihre Karte setzen. Tatsächlich können Sie mit der obigen Hash-Map mit der
map
Variablen nichts einfügen:Alle oben genannten Methodenaufrufe führen zu einem Fehler bei der Kompilierung, da Java den Wertetyp der darin enthaltenen HashMap nicht kennt
map
.Sie können immer noch einen Wert aus der Hash-Map abrufen. Obwohl Sie "den Typ des Werts nicht kennen" (weil Sie nicht wissen, welcher Typ von Hash-Map in Ihrer Variablen enthalten ist), können Sie sagen, dass alles eine Unterklasse von
Object
und, was auch immer Sie aus der Map herausholen, ist wird vom Typ Objekt sein:Der obige Codeblock gibt 10 auf der Konsole aus.
Verwenden
HashMap
Sie zum Abschluss ein mit Platzhaltern, wenn Sie sich nicht darum kümmern (dh es spielt keine Rolle), um welche TypenHashMap
es sich handelt, zum Beispiel:Andernfalls geben Sie die Typen an, die Sie benötigen:
Bei der obigen Methode müssten wir wissen, dass der Schlüssel der Karte ein ist
Character
, andernfalls würden wir nicht wissen, welchen Typ wir verwenden sollen, um Werte daraus zu erhalten. Alle Objekte haben jedoch einetoString()
Methode, sodass die Karte für ihre Werte einen beliebigen Objekttyp haben kann. Wir können die Werte immer noch drucken.quelle