Vererbung funktioniert nicht mit übergeben als generischer Typ

8

Betrachten Sie meine benutzerdefinierte erweiterte hashmap:

%Vor%

Warum funktioniert das nicht, da CustomHashMap ein Kind von HashMap ist?

%Vor%

Aber das funktioniert:

%Vor%

Und es funktioniert auch, wenn Sie eine CustomHashMap in die customs Map einfügen (einfügen).

%Vor%

Es scheint merkwürdig , dass die generics bei der Initialisierung nicht funktioniert , aber sonst nicht.

    
alex.dominte 14.11.2013, 11:33
quelle

3 Antworten

4

Wenn Sie mit Generika arbeiten, sollten Sie immer type löschen beachten. Zur Laufzeit kennt ein Objekt vom Typ Map seine Typparameter nicht mehr. Die Konsequenz: A LinkedHashMap<String, CustomHashMap> ist kein Untertyp von Map<String, HashMap<String, Object>> .

Wenn Sie etwas Sub-Typ haben wollen, müssen Sie folgendes tun:

%Vor%

Dies wird als oberer begrenzter Platzhalter bezeichnet und existiert genau für diesen Fall: Um eine Untertyp-Beziehung zu erhalten. Weitere Informationen finden Sie im Java-Lernprogramm zu Generika .

Eine zusätzliche Information laut Kommentar:

Die obere Version hat einen Nachteil bei der Verwendung der Zollkarte. Sie können keine Instanzen mehr in diese Map einfügen. Der einzige zulässige Wert ist null . Der Grund ist, dass Sie eine andere Klasse haben könnten, die Map<String, HashMap> erweitert und versucht, eine Instanz davon in Ihre Zollkarte zu bringen. Dies ist jedoch ein Problem, da sich der variable Zoll auf eine Karte bezieht, die mit CustomHashMap parametrisiert wurde.

Wenn Sie mit begrenzten Platzhaltern arbeiten, sollten Sie PECS immer daran erinnern. PECS steht für "Producer extends, consumer super". Dies ist wertvoll für Methodenparameter. Wenn Sie eine Methode schreiben, die nur Werte aus einer solchen Map lesen muss, können Sie den Parameter als Map<String, ? extends Map<String, Object>> eingeben. Dies nennt man einen Produzenten. Wenn Sie nur auf diese Karte schreiben müssen, verwenden Sie das Schlüsselwort super . Wenn Sie beide brauchen - lesen und schreiben - können Sie auch nicht.

    
Seelenvirtuose 14.11.2013, 11:48
quelle
7

Diese Anweisung funktioniert nicht

%Vor%

weil customs vom Typ Map<String, HashMap<String, Object>> ist und Sie eine LinkedHashMap vom Typ <String, CustomHashMap> zuweisen, wobei CustomHashMap eine Unterklasse von HashMap<String, Object> ist.

Generics sind invariant : für zwei unterschiedliche Typen T1 und T2 , HashMap<String, T1> ist weder ein Subtyp noch ein Supertyp von HashMap<String, T2> . Daher kann LinkedHashMap<String, CustomHashMap> nicht Map<String, HashMap<String, Object>> zugewiesen werden. Auf der anderen Seite sind Arrays covariant , was bedeutet, dass die Anweisung unten ohne einen Fehler oder eine Warnung kompiliert wird. Es kann jedoch zur Laufzeit fehlschlagen (was zu mehr Schaden führen kann), wenn Sie einen anderen Subtyp von HashMap<String, Object> als CustomHashMap einfügen:

%Vor%

Wenn Sie nun LinkedHashMap<String, CustomHashMap> zu Map<String, HashMap<String, Object>> zuweisen möchten, ändern Sie die Anweisung wie folgt:

%Vor%

Einige zusätzliche Informationen zu diesem Ansatz werden durch @Seelenvirtuose, die akzeptierte Antwort, erklärt.

    
Debojit Saikia 14.11.2013 11:44
quelle
2

Aus dem Java-Lernprogramm auf der Oracle-Website

%Vor%
  

Zeile 1 ist sicherlich legal. Der schwierigste Teil der Frage ist Zeile 2. Dies läuft auf die Frage hinaus: ist eine Liste von String eine Liste von Objekten. Die meisten Menschen antworten instinktiv: "Sicher!"

     

Sehen Sie sich die nächsten Zeilen an:

%Vor%
  

Hier haben wir ls und lo aliasiert. Wenn wir auf ls, eine Liste von String, über den Alias ​​lo zugreifen, können wir beliebige Objekte in sie einfügen. Als Ergebnis hält ls nicht mehr nur Strings, und wenn wir versuchen, etwas daraus zu machen, bekommen wir eine grobe Überraschung.

     

Der Java-Compiler wird das natürlich verhindern. Zeile 2 verursacht einen Kompilierzeitfehler.

dieser Link würde Ihnen helfen, Generika zu lernen und subtyping

    
quelle

Tags und Links