2017-08-07 1 views
-1

ich eine Karte erklärt haben, dieObjekt kann nicht in einem generischen Karte setzen

Verschachtelte Karten Lang eine verschachtelte Karte Abbildung von Tasten des Typs enthält Schlüssel von Typ Klasse und Werte von Typ SomeClient hat Grundsätzlich ich bin versucht, Generieren Sie eine Zuordnung des Klassentyps zu den Clients, die die Antwort des Klassentyps erzeugen.

private static final Map<Long, Map<Class<? super GenericResponse>, SomeClient<? super GenericResponse>>> someClientMap 
     = new HashMap<Long, Map<Class<? super GenericResponse>, SomeClient<? super GenericResponse>>>(); // <? super GenericResponse> should enable me to put subclasses of type GenericResponse in the Map 

Die getSomeClient Methode ist ein generisches Verfahren, das die Klasse Typ als Argument akzeptiert und gibt den Client, die Antworten der Klasse Typ produziert (Der Typ-Klasse kann nur eine Unterklasse von GenericResponse sein. Hinweis Type-Parameter in der Methodensignatur)

Das Problem ist, dass ich einen Kompilierzeitfehler erhalte, wo ich versuche, den Klienten in die Karte zu setzen.

Der genaue Fehler ist

The method put(Long, Map<Class<? super GenericResponse>,SomeClient<? super GenericResponse>>) in the type Map<Long,Map<Class<? super GenericResponse>,SomeClient<? super GenericResponse>>> is not applicable for the arguments (long, HashMap<Class<T>,SomeClient<T>>) 

Ich habe Schwierigkeiten zeigen, was genau mache ich falsch. Bitte helfen Sie.

Erklärung für SomeClient ist

public class SomeClient<T extends GenericResponse> 

und für den contructor ist

public SomeClient(Class<T> clazz) 
+0

Sieht aus wie das Problem ist in 'Long' vs' long' - Sie setzen 'long' Argument, Karte erwartet' Long'. Casting hinzufügen oder 'Long.valueOf (.)' Methode verwenden –

+0

Könnten Sie in der Frage die Deklaration von 'SomeClient' und' GenericResponse' posten? –

Antwort

0

Es gibt mehrere Probleme in Ihrem Code. Erstens, wenn Sie Subtypen zulassen möchten, sollten Sie extends verwenden und nicht super:

private static final Map<Long, Map<Class<? extends GenericResponse>, SomeClient<? extends GenericResponse>>> someClientMap 
     = new HashMap<Long, Map<Class<? extends GenericResponse>, SomeClient<? extends GenericResponse>>>(); 

Dies ist zu sagen, dass Sie Subtypen von GenericResponse als generische Parameter von Class und SomeClient im Map erlauben, aber es funktioniert nicht zulassen, Subtypen von Class (selbe für SomeClient) selbst zu verwenden, und für alle, die wir kennen Class<T> (wo T extends GenericResponse) ist ein Untertyp von Class<? extends GenericResponse>, wie ersteres ist eine "Spezialisierung" der letzteren für eine spezifische T.

diese Definition Verwenden Sie die gleichen generischen Parameter der inneren Map zu halten, wenn es in dem äußeren setzen:

someClientMap.put(clientId, new HashMap<Class<? extends GenericResponse>, SomeClient<? extends GenericResponse>>()); 

können Sie die put halten, wie Sie es aber haben, wenn man nur mehr hinzufügen extends an die Erstmeldung Subtypen von Class und SomeClient zu ermöglichen:

private static final Map<Long, Map<? extends Class<? extends GenericResponse>, ? extends SomeClient<? extends GenericResponse>>> someClientMap 
     = new HashMap<Long, Map<? extends Class<? extends GenericResponse>, ? extends SomeClient<? extends GenericResponse>>>(); 

und dann können Sie einfach tun:

someClientMap.put(clientId, new HashMap<Class<T>, SomeClient<T>>()); 

So oder so, werden Sie nicht von hässlichen Würfe weg, wenn someClientMap Zugriff:

return (SomeClient<T>) someClientMap.get(clientId).get(clazz); 
+0

Danke für die Antwort, aber ich habe super statt erweitert verwendet, weil ich verschiedene Unterklassen der GenericType-Klasse zu derselben Karte hinzufügen möchte. Bitte beziehen Sie sich auf diese Frage https://stackoverflow.com/questions/4343202/difference-between-super-t-and-extends-t-in-java für eine Erklärung. –

+0

@ rohit.agrawal Haben Sie die Antworten auf diese Frage gelesen? Es ist ziemlich einfach: Wenn Sie ** Unterklassen ** von GenericType erlauben möchten, benutzen Sie '? erweitert GenericType'; Wenn Sie ** Superklassen ** von GenericType erlauben wollen, benutzen Sie '? Super GenericType'. –

+0

Ich möchte nicht nur eine Unterklasse des GenericType in der Karte zulassen, ich möchte mehrere Subtypen in der gleichen Karte zulassen. Kopieren Sie einige Teile der Antwort in den Link hier, um zu betonen, was ich sage. Wenn eine Liste als 'List foo3'; Sie können keine Ganzzahl hinzufügen, da foo3 auf eine Liste zeigen könnte. Sie können kein Double hinzufügen, da foo3 auf eine Liste zeigen könnte. Sie können keine Zahl hinzufügen, da foo3 auf eine Liste zeigen könnte. –

0

Der Fehler auf die Tatsache zurückzuführen ist, dass Java Generika invariant, sind dobwohl String ein Subtyp von Object die folgende Zeile wird nicht kompilieren:

Map<Long, Object> map = new HashMap<Long, String>(); 

weil Map<Long, String> kein Subtyp von Map<Long, Object> ist.

Aber wir können mit beschränkten Platzhalter über diese Einschränkung erhalten, das heißt

Map<Long, ? extends Object> map = new HashMap<Long, String>(); 

Diese warum es ein Class<? super GenericResponse> in Ihrem Code, aber Sie hielten etwa auf halbem Weg. Sie sollten die gleiche Technik in der nächsthöheren Ebene, dh Schreib verwendet:

Map<Long, Map<? extends Class<? extends GenericResponse>, ? extends SomeClient<? extends GenericResponse>>> 

statt

Map<Long, Map<Class<? extends GenericResponse>, SomeClient<? extends GenericResponse>>> 

Durch die Art, wie ich ersetzt habe ? super mit ? extends in meinem Beispiel, weil ich glaube, Sie don verwende sie nicht richtig.

-1

Ich habe das Problem herausgefunden. In der folgenden Anweisung

Die neue HashMap, die ich erstelle, ist restriktiver als das, was die äußere Karte akzeptiert. seit T erweitert GenericResponse in der generischen Methode.

Die Erklärung ermöglicht verschiedene Unterklassen der GenericResponse Klasse in der gleichen Karte gespeichert werden, da ich verwende Super

private static final Map<Long, Map<Class<? super GenericResponse>, SomeClient<? super GenericResponse>>> someClientMap 
    = new HashMap<Long, Map<Class<? super GenericResponse>, SomeClient<? super GenericResponse>>>(); // <? super GenericResponse> should enable me to put subclasses of type GenericResponse in the Map 

Bitte beachte Difference between <? super T> and <? extends T> in Java für eine sehr gute explaination desselben.

das Problem beheben ich die Put-Anweisung

someClientMap.put(clientId, new HashMap<Class<? super GenericResponse>,SomeClient<? super GenericResponse>>()); 

Diese Put stellt sicher, dass die innere Karte in der Tat ersetzt Instanzen verschiedener Unterklassen der GenericResponse Klasse halten kann, wie in der Erstmeldung erklärt wurde.

+0

Sie verwenden '? Super GenericResponse "aber im Text sagen Sie, dass Sie" Instanzen von verschiedenen ** Unterklassen ** der 'GenericResponse" Klasse halten müssen - das ist verwirrend, verwenden Sie entweder '? Super GenericResponse' und sagen "Superklassen der' GenericResponse' Klasse "oder verwenden'? extendiert GenericResponse' und sagt "subclasses der' GenericResponse' Klasse " –

+0

wenn ich und sagen "halten Instanzen der verschiedenen Unterklassen der GenericResponse-Klasse" Ich meine es. Es ist ein wenig kontraintuitiv, aber so ist es. Bitte beachten Sie die akzeptierte Antwort für https://stackoverflow.com/questions/4343202/difference-between-super-t-and-exends-t-in-java für eine sehr gute Erklärung des gleichen. –

+0

Sie haben Recht, danke für den Link –

Verwandte Themen