Sehen Sie sich dieses einfache Beispiel für Java-Generics an:
%Vor%Es wird ein Fehlerkompiliervorgang ausgeführt, der behauptet, dass die Typen inkompatibel sind, behauptet jedoch, dass die beiden Variablen vom selben Typ sind:
%Vor% Wenn ich die erste Zeile von length () in List<T> l = (List<T>)(Object)this.l;
ändere, funktioniert es. Warum?
Sie haben eine generische Methode in einer generischen Klasse mit dieser Zeile deklariert:
%Vor% Diese <T>
unterscheidet sich von der <T>
Ihrer Klasse. Nach dem JLS Abschnitt 6.3 :
Der Geltungsbereich des Typparameters einer Klasse (§8.1.2) ist der Typparameter Abschnitt der Klassendeklaration, der Typ Parameterabschnitt von jedem Superklasse oder Superschnittstelle der Klassendeklaration und der Klasse Körper.
Sie müssen <T>
für Ihre Methode nicht erneut deklarieren. Der Typparameter der Klasse ist bereits im Bereich.
Um den generischen Typparameter <T>
Ihrer Klasse zu verwenden, muss Ihre Methode keine weitere <T>
deklarieren und einfach die <T>
Ihrer Klasse verwenden:
Um zu verstehen, warum Ihr Casting funktioniert:
%Vor% Sie können jedes Objekt in Object
umwandeln. Dann werfen Sie das Ergebnis auf List<T>
. Du kannst es immer auf alles übertragen, was du willst. Java wirft zur Laufzeit einfach ClassCastException
, wenn es zur Laufzeit nicht wirklich ein List
war. Aber der Compiler wird auch warnen, dass er ungeprüfte oder unsichere Operationen verwendet, weil er nicht garantieren kann, dass diese <T>
die ursprüngliche <T>
ist.
Um den Unterschied zwischen <T>
s zu veranschaulichen, können Sie <U>
als generischen Typparameter für die Methode verwenden und die gleichen Ergebnisse erhalten:
Dies wird mit der gleichen Art von Sicherheitswarnung kompiliert.
Wenn Sie wirklich wissen, dass Typsicherheit garantiert werden kann, können Sie @SuppressWarnings("unchecked")
verwenden, um Ihre Methode zu kommentieren. Aber hier würde ich immer noch den generischen Typparameter vollständig aus der Methode entfernen und den Typparameter der Klasse verwenden.