Generika Generika und Generika? Zuordnungen

8

Manchmal bekomme ich einfach keine Generika. Ich verwende oft die allgemeinste Version der Sammlungen im Code. Zum Beispiel, wenn ich eine Menge von irgendetwas brauche, würde ich etwas schreiben wie:

%Vor%

Es ist vom Compiler erlaubt und warum sollte es nicht - Set<?> ist so allgemein wie Set<Object> (oder noch generischer ..). Wenn ich jedoch "Generika von Generika" benutze, die es "generischer" machen, funktioniert das nicht:

%Vor%

Was ist los? Warum ist Set<Object> zuweisbar zu Set<?> und Set<Class<Object>> ist nicht zu Set<Class<?>> zuweisbar?

Ich finde immer einen Weg um diese Art von Problemen zu finden, aber in diesem Fall möchte ich wirklich wissen, warum dies nicht erlaubt ist und nicht ein Workaround.

    
dacwe 25.05.2012, 09:56
quelle

5 Antworten

5

Generika sind in Java nicht kovariant. Diese Frage kann Ihnen helfen:

Java-Generika-Kovarianz

    
Matthias Meid 25.05.2012, 10:06
quelle
5

Gegeben:

%Vor%

Das funktioniert, wenn Sie sich ansehen, was der unbeschränkte Platzhalter bedeutet, der geschlitzte Typ auf unbeschränkter Wildcard wird mit dem extends verglichen, also wenn Sie das explizit tun.

%Vor%

Zu lesen, ist Großartiges Objekt? Ja, so dass kompiliert.

Dann gegeben:

%Vor%

Warum es funktioniert, wenn Sie den Parameter Set und HashSet extrahieren, sind sie Class<Great> , diese beiden Class<Great> sind genau vom selben Typ.

In Abwesenheit von Platzhalterzeichen werden Typen direkt in Verbatim verglichen.

Und wenn wir das set3 so schreiben, dass es den kovarianten Typ akzeptiert (kompiliert):

%Vor%

Um zu lesen, ist HashSets Class<Great> typenkompatibel oder kovariant gegen Set's Class<Great> ? Ja, so ist es. Daher kompiliert es.

Natürlich würde niemand diese Art von Variablendeklaration schreiben, wenn sie genau vom selben Typ sind, es ist überflüssig. Der Platzhalter wird vom Compiler verwendet, um festzustellen, ob der konkrete Klassen- oder Schnittstellenparameter des Generikers auf der rechten Seite der Zuweisung mit dem konkreten / interface der linken Seite kompatibel ist (idealerweise wie folgt).

%Vor%

Um es zu lesen, ist HashSet<Great> kovariant zu Set<Great> ? Ja, so ist es. Daher kompiliert es

Kommen wir also zu Ihrem Codeszenario zurück:

%Vor%

In diesem Fall gilt die gleiche Regel, Sie lesen es von innen beginnend, ist Objekt kompatibel zu Wildcard? Ja. Danach gehst du zum nächsten äußersten Typ, der keine Wildcard hat. In Abwesenheit von Wildcard wird der Compiler zwischen Class<Object> und Class<?> eine Verbatim-Prüfung durchführen, die nicht gleich ist, daher ein Kompilierfehler.

Wenn es am äußersten Platzhalter hat, wird das kompiliert. Was Sie wahrscheinlich damit gemeint haben, ist dies kompiliert :

%Vor%

Lassen Sie uns ein aufschlussreicheres Beispiel geben, benutzen wir die Schnittstelle (Klasse ist konkreter Typ), sagen wir Set. Dies kompiliert:

%Vor%

Also lies es von innen nach außen, um herauszufinden, warum dieser Code kompiliert wird, und mache es explizit:

  1. Innerste: Ist Object kompatibel zu ? Extends Object ? Sicher ist es.

  2. Äußerste: Ist HashSet<Object> kompatibel zu ? extends Set<? extends Object> ? sicher ist es.

Bei Nummer 1 ist dies (kompiliert):

%Vor%

Bei Nummer 2 ist dies (kompiliert):

%Vor%

Versuchen wir nun, den äußersten Platzhalter zu entfernen. Es würde keine typenkompatible / kovariante Überprüfung durch den Compiler geben, die Dinge werden nun wörtlich miteinander verglichen.

Sie wissen also jetzt die Antwort auf die folgenden, sollen diese kompilieren?

%Vor%

Also rätst du es schon, richtig ... das wird nicht kompilieren: -)

Um das oben genannte zu korrigieren, machen Sie einen der folgenden Schritte:

%Vor%

Um Ihren Code zu korrigieren, führen Sie dann einen der folgenden Schritte aus:

%Vor%     
Michael Buen 30.05.2012 20:09
quelle
0

Ich habe folgendes in Eclipse unter jdk1.6.0_22 versucht:

%Vor%

Compiler gab mir folgendes:

%Vor%

Ich habe es geändert und es hat funktioniert:

%Vor%

Scheint so, als ob Generika von Generika dieselbe Klasse von Sammlungen und dieselbe Klasse des gesammelten Objekts haben müssen.

Dies scheint eine Regel in Java zu sein, vielleicht wegen der hohen Fehleranfälligkeit zur Laufzeit, die zu größeren Abstürzen führen könnte. Wenn man es so schreibt, wird es auch funktionieren:

%Vor%     
GingerHead 25.05.2012 10:08
quelle
0
%Vor%

Dies sagt: ein Satz von Klassen eines beliebigen Typs

%Vor%

Das sagt: ein HashSet von Klassen, die vom Typ Object sein müssen - also nur Object.class-Objekte erlaubt sind - was wenig Sinn macht, da es nur ein Klassenobjekt für Object gibt.

Ich denke, dass die Frage immer noch gültig ist, aber vielleicht könnten Sie eine andere Stichprobe als die Klasse wählen.

    
Puce 25.05.2012 10:23
quelle
-1

Hier ist die Antwort, dass es jede Art von Objekttyp akzeptiert.

Daher müssen Sie unter das Ding schreiben

%Vor%

Hier können Sie jede Art von Object in Set

speichern     
Bhavik Ambani 25.05.2012 10:08
quelle

Tags und Links