Ich habe eine Legacy-Klasse, die die Klasse selbst nicht generisch ist, aber eine ihrer Methoden Rückgabetyp verwendet Generics:
%Vor% getStuff()
verwendet Generics, um eine Sammlung von Strings zurückzugeben. Daher kann ich über getStuff()
iterieren und die Elemente müssen nicht in ein String
:
Wenn ich jedoch Thing
selbst als generisch ändere, aber alles andere gleich behalte:
und verwenden Sie dann weiterhin den nicht generischen Verweis auf Thing
, getStuff()
gibt nicht mehr Collection<String>
zurück und gibt stattdessen einen nicht typisierten Collection
zurück. Daher kompiliert der Client-Code nicht:
Warum ist das? Was sind die Problemumgehungen?
Meine Vermutung ist, dass Java durch die Verwendung einer nicht-generischen Referenz auf eine generische Klasse alle Generika für die gesamte Klasse deaktiviert. Das ist Schmerz, denn jetzt habe ich meinen Client-Code gebrochen, indem ich Thing zu einem generischen gemacht habe.
Bearbeiten: Ich mache Thing generisch für eine andere Methode, die im obigen Beispielcode nicht aufgeführt ist. Meine Frage ist lehrreich, warum das oben Gesagte nicht gemacht werden kann.
Ok, nimm zwei, ich habe deine Frage missverstanden.
Wenn Sie delcare Thing
(das heißt ein raw type ) anstelle von Thing<?>
( parametrisierter Typ ) verwenden, entfernt der Java-Compiler alle generischen Argumente selbst thogh (wie in Ihrem Fall) hat der generische Typ der Methode nichts mit dem generischen Typ der Klasse zu tun.
Von der (ausgezeichneten) Java Generics FAQ :
Kann ich Verwenden Sie einen Rohtyp wie jeder andere Typ?
Methoden oder Konstruktoren eines Rohtyps haben die Signatur, die sie nach dem Typ löschen würden.
Dieser scheinbar unschöne und unaufdringliche Satz beschreibt das fragliche Verhalten. Sie verwenden Thing
als unformatierten Typ, daher ist der Rückgabetyp Collection
(nicht Collection<String>
), da dies der Typ nach dem Typ löschen ist.
Verwirrt? Nicht überraschend. Schau dir einfach die Größe dieser FAQ an. Es gibt wahrscheinlich drei Menschen auf der Erde, die die volle Bedeutung von Java Generics verstehen. Bedenken Sie einfach meine Lieblingserklärung aus dem JDK:
%Vor%(Es gibt auch eine Erklärung dazu in der FAQ).
Es versagt wegen Löschung. Sie können mehr darüber in diesen Java-Lernprogrammen
lesen Ich denke, das ist völlig normal. Meiner Meinung nach mit Thing t = new Thing (); für generische aktivierte Klasse ist total ein Fehler. Wenn der Compiler eine generische Klasse als Klasse ohne Typparameter verwendet, muss er alle generischen Typen aus dieser Klasse löschen. So können Sie alte Codes ohne Verwendung von Generika in neuen Java-Compilern kompilieren, und der Compiler ließ diese alten Codes generisch aktivierte Klassen (z. B. java.util.ArrayList) ohne irgendein Problem verwenden. (Und so braucht Java System.Collection.Generic.List und System.Collection.List nicht wie C # zu trennen). Sie können Thing t = new Thing();
ausführen, indem Sie einen einfachen Typparameter hinzufügen, Thing<Object> t = new Thing<Object>();
, nur etwas, das der Java-Compiler benötigt, stellt sicher, dass Sie java generic bewusst verwenden. Ich kann Java nie für seine große Rückwärtskompatibilität verantwortlich machen.
Ich weiß, ich bin ein bisschen spät: D