Wieso HashMap-Zugriff mit Object, statt mit MyObject?

Status
Nicht offen für weitere Antworten.

Professor Chaos

Aktives Mitglied
Hi,

ich habe eine rein technische Verständnisfrage.
Es gibt doch nun seit einiger Zeit (seit Java 6?) die Parametrisierung (oder wie man das sonst nennen mag), also Typensicherheit. Sprich, man gibt Datenstrukturen nun an, was man hineinspeichert.

Zum Beispiel hier:
Code:
HashMap<Integer,String> mappingInt2String = new HashMap<Integer,String>();

Ich verstehe nicht, wieso der Eclipse Syntaxchecker es zulässt, dass man in die get()-Methode beliebige Onjekte reinsteckt.
Eine smart-ass-Antwort würde wohl lauten: Weil der Prototyp der get()-Methode eben Object als Argument hat.
Doch ich frage nach dem "Wieso"!

Schließlich ist Eclipse doch auch intelligent genug, zu erkennen, was ich reinstecken darf. D.h. die Zeile
Code:
mappingInt2String.put(new Integer(42), new Integer(23));
wird korrekter Weise als Fehler angezeigt: "Ich solle doch bitte (Integer,String) reinstecken, und nicht (Integer,Integer)".

Wieso meckert Eclipse also nicht bei folgender Zeile?
Code:
mappingInt2String.get("strange...");

Bzw., um Spitzfindigkeiten auszuschließen: wieso beinhaltet der Prototyp von get() den Argumenttypen "Object", statt den "von mir" angegebenen Typen (in diesem Fall "Integer")?


--------
Falls dieses Thema von einem Admin gelesen werden sollte:
Könnte dieser den Titel nach "Wieso HashMap-Zugriff mit Object, statt mit MyObject?" ändern?
Ich erhalte (wie auch andere) die Meldung "Der Titel darf aus Spamschutzgründen nicht XXX sein!"
 

Eminent

Bekanntes Mitglied
Erstmal grundsätzliches: Eclipse oder andere IDEs haben RECHT hier nicht zu meckern es ist so implementiert.

Wieso SUN das so implementiert hat weiß ich nicht, wie Gast schon sagte, vielleicht aus Gründen der Abwärtskompatibilität.

Die Implementation der GET-Methode in java.util.Map ist aber so:

Code:
    /**
     * Returns the value to which the specified key is mapped,
     * or {@code null} if this map contains no mapping for the key.
     *
     * 

More formally, if this map contains a mapping from a key
     * {@code k} to a value {@code v} such that {@code (key==null ? k==null :
     * key.equals(k))}, then this method returns {@code v}; otherwise
     * it returns {@code null}.  (There can be at most one such mapping.)
     *
     * 

If this map permits null values, then a return value of
     * {@code null} does not [i]necessarily[/i] indicate that the map
     * contains no mapping for the key; it's also possible that the map
     * explicitly maps the key to {@code null}.  The {@link #containsKey
     * containsKey} operation may be used to distinguish these two cases.
     *
     * @param key the key whose associated value is to be returned
     * @return the value to which the specified key is mapped, or
     *         {@code null} if this map contains no mapping for the key
     * @throws ClassCastException if the key is of an inappropriate type for
     *         this map (optional)
     * @throws NullPointerException if the specified key is null and this map
     *         does not permit null keys (optional)
     */
    V get(Object key);

während für die PUT-Methode die "passente" Implementation (mit Generics) gewählt wurde:

Code:
    /**
     * Copies all of the mappings from the specified map to this map
     * (optional operation).  The effect of this call is equivalent to that
     * of calling {@link #put(Object,Object) put(k, v)} on this map once
     * for each mapping from key <tt>k</tt> to value <tt>v</tt> in the
     * specified map.  The behavior of this operation is undefined if the
     * specified map is modified while the operation is in progress.
     *
     * @param m mappings to be stored in this map
     * @throws UnsupportedOperationException if the <tt>putAll</tt> operation
     *         is not supported by this map
     * @throws ClassCastException if the class of a key or value in the
     *         specified map prevents it from being stored in this map
     * @throws NullPointerException if the specified map is null, or if
     *         this map does not permit null keys or values, and the
     *         specified map contains null keys or values
     * @throws IllegalArgumentException if some property of a key or value in
     *         the specified map prevents it from being stored in this map
     */
    void putAll(Map<? extends K, ? extends V> m);

Wie gesagt wieso das so implementiert ist weiss ich auch nicht aber Eclipse liegt hier auf jeden Fall richtig.

Gruß
Eminent
 

Lim_Dul

Top Contributor
Ich vermute mal, der Grund liegt - wie so vieles bei Generics - am Type Erasure.

Wenn man der get-Methode ein Object einer falschen Klasse übergibt, passiert erstmal nichts falsches, es kann dabei zu keiner ClassCastException kommen, da das Objekt nicht in der Map gespeichert wird.

Interessant wird der Fall, wenn man Wildcards arbeitet. Ich hole jetzt mal was aus.

Code:
List <? extends Number> myList;

Hier kann man die add-Methode nicht aufrufen, da der genaue Typ der Liste unbekannt ist.
Es könnte eine List<Number> sein oder eine List<Long> oder eine List<Float>. Und es gibt keinen Typ, der zu allen 3 Klassen (Number, Long, Float) passt.

Dafür liefert die get-Methode ein Number-Objekt, da klar ist, dass mindestens Numbers in der Liste stecken.

Nun der umgekehrte Fall:
Code:
List <? super Number> myList;

Hier kann man die Add-Methode mit Number aufrufen, da man weiß, dass der Typ, den die Liste hat eine Oberklasse von Number ist, also auf jeden Fall Number darauf gecastet werden kann.

Dafür liefert die get-Methode ein Objekt vom Typ Object, da man nicht weiß welcher Obertyp in der Liste steckt.

Zusammenfassend:
Bei Wildcards extends sind Methoden mit generischen Parametern nicht aufrufbar, Methoden mit generischen Rückgabeparametern liefern den entsprechenden Typ.
Bei Wildcards super sind Methoden mit generischen Parametern aufrufbar, Methoden mit generischen Rückgabeparametern liefern Object.

Und nun wieder zurück zur Map:
Würde die get-Methode einen generischen Typ haben, so könnte sie, sobald man für den Key die Wildcard mit extends nimmt, nicht mehr aufgerufen werden. Nimmt man die Wildcard mit super, liefert sie Object zurück. Beides unschön.
Durch die Wahl von Object als Parameter kann man die Methode bei Wildcards mit extends aufrufen und bekommt den entsprechend schönen Rückgabewert.

Ob das der Grund für die Entscheidung war, weiß ich nicht, kann es mir jedoch gut vorstellen.
 

Marco13

Top Contributor
Ich hatte mir (und dem Forum :wink: ) die gleiche Frage auch mal gestellt http://www.java-forum.org/de/viewtopic.php?t=52402 aber keine wirklich überzeugende, abschließende Antwort erhalten... Das Web liefert Antworten von "Ist doch egal" bis "Abwärtskompatibilität" bis "Funktioniert nicht". Hm. Ich denke inzwischen, dass es einige ... "oddities" erzeugen würde.
Wie auch immer. Laut http://java.sun.com/j2se/1.5.0/docs/api/java/util/Map.html#get(java.lang.Object) kann die Methode "optional" eine ClassCastException werfen, wenn der falsche Typ übergeben wird.
 

Professor Chaos

Aktives Mitglied
Marco13 hat gesagt.:
Laut http://java.sun.com/j2se/1.5.0/docs/api/java/util/Map.html#get(java.lang.Object) kann die Methode "optional" eine ClassCastException werfen, wenn der falsche Typ übergeben wird.
Tatsächlich, siehe:
Java API hat gesagt.:
V get(Object key)[...]
Throws:
ClassCastException - if the value is of an inappropriate type for this map (optional).
Aber wie soll das funktionieren? Denn ich möchte ja gerade, dass Eclipse einen Fehler (keine Warnung) wirft, wenn ich mit einem key zugreife, der einen anderen Typ hat, als angedacht. Ich möchte also genau diese optionale Exception. Aber wie teile ich mit, dass diese auch geworfen werden soll? Die API schweigt sich dazu aus.
 

Professor Chaos

Aktives Mitglied
Lim_Dul hat gesagt.:
Das teilst du nicht mit, das "entscheidet" die entsprechende Implementierung der Map
Ach, natürlich. Ich habe nicht gesehen, dass ich mich in der Documentation des Interfaces befand. Ich dachte, das wäre die Documentation der konkreten Klasse HashMap.
Schade.
Gut, man könnte natürlich eine eigene Klasse MyHashMap anlegen, die gänzlich identisch ist und lediglich get() überschreibt. Aber ist das schön? Ich passe wohl besser auf, was ich tue, statt eigene Klassen einzuführen.
 

Der Müde Joe

Top Contributor
einer der Autoren (J.Bloch) der Collection API spricht darüber.

Well, It's typesafe..
..in order to maximize backward compatibility...
In fact, when we were generifying the collection....we tried to attempt this restriction but we find out it simply didn't work

weils generisch nicht so gut geht gewisse Dinge zu implementieren
Abwärtskompatibilität...

auch remove und contains ist so...
man kann JFrame von Set<String> entfernen..bekommt
einfach null zurück...dito get bei Map...

so kurz gesagt...
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
Zrebna Wieso sollte man Null-Prüfungen nicht mit Optional-Objekten nutzen? Allgemeine Java-Themen 13
Zrebna Wieso sind eigentlich JUnit-Tests in src/test/java platziert - nur Konvention? Allgemeine Java-Themen 7
P Wieso benutzen PriorityQueues Heaps? Allgemeine Java-Themen 2
Y Wieso krieg ich die Unit Tests nicht hin Allgemeine Java-Themen 55
I Wieso funktioniert das nich? Allgemeine Java-Themen 5
F Input/Output NullPointerException, aber wieso? [Apache POI] Allgemeine Java-Themen 11
R MAC-Adresse eindeutig für einen PC ? Bezug zu Netzwerk, wieso ? Allgemeine Java-Themen 7
P Best Practice Wieso funktioniert der Modulo - Operator nicht? Allgemeine Java-Themen 2
J Jasper ireport - wieso beendet die Anwendung wenn ich die Preview schließe Allgemeine Java-Themen 1
I Interface Interface / Klasse - wieso Abstract? Allgemeine Java-Themen 13
A Methoden Generische Methode mit Arrays - Source Compatibility 1.7 benötigt, wieso? Allgemeine Java-Themen 3
S RemoteException wieso ? Allgemeine Java-Themen 6
J if else Anweisung macht nicht was es soll. Wieso? Allgemeine Java-Themen 10
P wieso kann ich auf bluej exportieren aber auf eclipse nicht? Allgemeine Java-Themen 2
DEvent Wieso ist Javadoc mit Html Tags? Allgemeine Java-Themen 47
D java.util.InputMismatchException im Scanner -wieso? Allgemeine Java-Themen 5
E Wieso returnt das hier 1? Allgemeine Java-Themen 3
DStrohma [Erledigt] Wieso kann ich Taste 'ENTER' in JTable nicht belegen? Allgemeine Java-Themen 2
C Wieso funktioniert das? Allgemeine Java-Themen 6
W Wieso funktioniert dieser Code hier? Allgemeine Java-Themen 6
S Wieso stehen in der API immer wieder abstrakte Methoden ? Allgemeine Java-Themen 7
lacyuu Schleife hängt sich auf, wieso?? Allgemeine Java-Themen 2
V Wieso meckert FindBugs da? Allgemeine Java-Themen 7
V Wieso Heap Space Problem? Allgemeine Java-Themen 14
J Wieso implementiert HTTPServlet Serializable? Allgemeine Java-Themen 2
P Wieso skalieren diese beiden Threads unterschiedlich gut? Allgemeine Java-Themen 16
zilti Wieso geht der StreamReader/Writer nicht? Allgemeine Java-Themen 5
T Wieso erfolgt keine Ausgabe. /Excel Allgemeine Java-Themen 19
G wieso wird der String des StringBuilder immer länger? Allgemeine Java-Themen 2
G wieso "implements" Allgemeine Java-Themen 13
S Problem mit generics -> ClassCastException und ka wieso Allgemeine Java-Themen 20
G Übergabe funzt nicht, aber wieso? Allgemeine Java-Themen 3
G NullPointer ? wieso? Allgemeine Java-Themen 7
I Wieso läuft Programm bei Kollegen aber nicht bei mir? Allgemeine Java-Themen 10
OnDemand Java String in Hashmap als Key NULL Allgemeine Java-Themen 27
T HashMap values Bearbeitung Allgemeine Java-Themen 4
T Hashmap Values Bearbeitung Allgemeine Java-Themen 1
JavaJakob22 Bestimmte HashMap importieren Allgemeine Java-Themen 4
killig HashMap mit if-Anweisung überprüfen Allgemeine Java-Themen 4
killig Textdatei einlesen und in HashMap speichern (duplikate entfernen) Allgemeine Java-Themen 12
LimDul Kam eine java.net.URL zu einer HashMap und ging als DNS Anfrage wieder heraus Allgemeine Java-Themen 18
L HashMap Allgemeine Java-Themen 10
X Collections Gibt es eine Klasse welche die Vorteile von List und HashMap vereint, aber konstante Laufzeit (O(1)) hat in Java? Allgemeine Java-Themen 4
B HashMap Duplikate Allgemeine Java-Themen 4
A HashMap Methode "get()"-Problem Allgemeine Java-Themen 28
W Array vs. ArrayList vs. HashMap Allgemeine Java-Themen 20
F Tabelle aus CSV, 2 dimensionale HashMap? Allgemeine Java-Themen 4
D Mit Java PHP hashmap lesen Allgemeine Java-Themen 1
H Swing HashMap zu Tabelle macht mir Probleme Allgemeine Java-Themen 4
B HashMap aus Value Key bekommen Allgemeine Java-Themen 2
N HashMap und Methoden richtig einbinden Allgemeine Java-Themen 2
J Problem bei Hashmap Key-Abfrage Allgemeine Java-Themen 4
X JSONObject auslesen und in HashMap hinterlegen Allgemeine Java-Themen 16
N Werte aus Hashmap auslesen und übertragen Allgemeine Java-Themen 8
JavaWolf165 JsonObject in HashMap umwandeln Allgemeine Java-Themen 16
R ArrayList und HashMap Allgemeine Java-Themen 7
L Assoziatives Datenfeld, schneller wie Hashmap Allgemeine Java-Themen 35
G Methoden HashMap speichert unter falschen Schlüsseln Allgemeine Java-Themen 6
D Verschachtelte HashMap initializieren Allgemeine Java-Themen 1
L Variablen HashMap nimmt value nicht an Allgemeine Java-Themen 3
R Hierarchie mit HashMap darstellen Allgemeine Java-Themen 19
D Datentypen HashCollision in HashMap Allgemeine Java-Themen 3
Z Concurrent Modification Exception - HashMap (kein remove) Allgemeine Java-Themen 4
B Zugriff auf eine HashMap Allgemeine Java-Themen 4
B Userdaten in Hashmap speichern - Servlet Allgemeine Java-Themen 6
T Hashmap mit geordneter/ungeordneter liste als Value Allgemeine Java-Themen 5
I HashMap key wird nicht erkannt trotz überschriebener equals/hashCode Methode Allgemeine Java-Themen 6
M Füllfaktor einer Hashmap Allgemeine Java-Themen 7
A Collections HashMap.containsKey findet keine immutablen Objekte Allgemeine Java-Themen 3
D Datentypen HashMap Allgemeine Java-Themen 5
R Collections Performance einer HashMap Allgemeine Java-Themen 26
C LinkedList und ArrayList in HashMap Allgemeine Java-Themen 4
T Erste Schritte HashMap<String, int> Allgemeine Java-Themen 2
K Hashmap sortieren Allgemeine Java-Themen 6
F HashMap überschreibt Daten von anderen HashMap Allgemeine Java-Themen 5
S HashMap containsKey liefert immer false zurück Allgemeine Java-Themen 15
H Problem beim Sortieren einer HashMap mit TreeSet Allgemeine Java-Themen 4
K HashMap sorting verhindern Allgemeine Java-Themen 10
J Generic von einer ArrayList/HashMap bekommen Allgemeine Java-Themen 7
L HashMap mit Enum Keys Allgemeine Java-Themen 3
J Array als Schlüssel für HashMap Allgemeine Java-Themen 6
S Geschwindigkeit HashMap oder .getParent Allgemeine Java-Themen 5
V Hashmap-Frage Allgemeine Java-Themen 3
M HashMap - Ich bin verwirrt Allgemeine Java-Themen 3
H2SO3- multiple Hashmap Allgemeine Java-Themen 5
K Threading - schreiben auf Hashmap/löschen - ConcurrentModificationException Allgemeine Java-Themen 3
J NullPointerException mit HashMap Allgemeine Java-Themen 2
V Probleme mit eigener Hashmap Allgemeine Java-Themen 10
N HashMap<String,Vector<String>> a = new HashMap<String,Vector<String>>(); Allgemeine Java-Themen 4
I HashMap Problem... Allgemeine Java-Themen 3
C HashMap Allgemeine Java-Themen 12
Daniel_L Map/HashMap - Reihenfolge von Einträgen Allgemeine Java-Themen 4
L HashMap Key Reihenfolge umkehren Allgemeine Java-Themen 8
N wie greife ich auf hashmap in vector zu Allgemeine Java-Themen 9
J Inhalt von HashMap vergleichen Allgemeine Java-Themen 3
Z Serialisierung und Deserialisierung einer HashMap Allgemeine Java-Themen 17
K Serialisierung von Hashmap in Vector Allgemeine Java-Themen 3
T Hashmap füllen mit rs sortierung Allgemeine Java-Themen 9
D HashMap sortieren Allgemeine Java-Themen 2
P Große Datenmenge wie speichern (HashMap? TreeMap?) Allgemeine Java-Themen 11

Ähnliche Java Themen


Oben