Ich habe Vorlesungen über Algorithmen auf Coursera von Robert Sedgewick durchgemacht. Ich war etwas verwirrt, als Mr. Robert darauf hinwies, dass man Generics mit Arrays nicht verwenden kann, wie es nicht erlaubt ist. Aber ArrayList in Collection Framework verwendet Arrays intern und generische Datentypen sind erlaubt. Ich meine, dass wir Folgendes tun können:
%Vor%Ein Hack, auf den er hingewiesen hat, war folgendes:
%Vor%Er erwähnte auch, dass dies ein hässlicher Hack ist und vermieden werden muss, und er erzeugt auch eine Warnung während der Kompilierung.
Meine Frage ist:
1.) Wie repräsentiert ArrayList dann intern verschiedene Generics-Typen?
2.) Wenn (angenommen) sie den oben erwähnten Hack verwenden, warum erzeugt sie keine Warnung, wenn wir ein Programm mit ArrayList kompilieren?
3.) Gibt es einen besseren Weg als oben beschrieben?
Pro Quelle:
1 - ArrayList
speichert Elemente in Object[]
und wandelt den Wert beim Abrufen einzelner Elemente um. Es gibt tatsächlich eine @SuppressWarnings("unchecked")
, in der die Besetzung stattfindet.
2 - Zwei Antworten hier - die erste besteht darin, dass Sie ArrayList
nicht (in der Regel) kompilieren, sondern nur von rt.jar
im JRE / JDK in Ihren Klassenpfad aufnehmen. Die zweite besteht darin, dass ArrayList
eine @SuppressWarnings
für die ungeprüfte Konvertierung von Object
in den generischen Typ verwendet.
3 - Ihre andere Alternative ("besser" ist ziemlich subjektiv) wäre, dass Class
für Ihren generischen Typ benötigt wird und Array.newInstance(Class clazz, int capacity)
verwendet wird, um Ihr Array zu erstellen, wie in diese Frage
1.) Wie repräsentiert ArrayList dann intern verschiedene Generics-Typen?
Was meinst du "intern"? Generics existieren nur zur Kompilierzeit. ArrayList
wurde bereits von jemand anderem für Sie kompiliert und Sie verwenden nur die Klassendatei. Es gibt also keine Generika.
Verschiedene Java-Bibliotheksimplementierungen könnten die Quelle anders schreiben, aber das interessiert Sie nicht. Was es "intern" macht, ist ein internes Implementierungsdetail, das ein Benutzer der Klasse nicht interessieren sollte.
Wenn Sie Ihre eigene Klasse wie FixedCapacityStack
schreiben würden, könnten Sie das auf verschiedene Arten tun:
s
vom Typ Item[]
ist, wie du oben gezeigt hast, und du erstellst Object[]
und wirfst auf Item[]
s
vom Typ Object[]
erstellen und in Item
umwandeln, wenn Sie Elemente daraus erhalten Beachten Sie, dass beide Ansätze nach dem Löschen gleich sind, also werden beide auf den exakt gleichen Bytecode kompiliert. Der Unterschied ist nur Stil zur Kompilierzeit.
Der Vorteil des ersten Ansatzes gegenüber dem zweiten besteht darin, dass es, wenn man Elemente herausholt, bereits der richtige Typ ist, so dass man nicht all diese hässlichen Modelle überall hat. Der Nachteil des ersten Ansatzes ist, dass die erste Umwandlung von Object[]
nach Item[]
im Grunde genommen eine "Lüge" ist und nur funktionieren wird, wenn Sie absolut sicher sind, dass s
nicht außerhalb der Klasse liegt (z keine Methode haben, die s
als Typ Item[]
) zurückgibt; Andernfalls haben Sie an unerwarteten Stellen Ausnahmen für die Klassenübergabe.
2.) Wenn (angenommen) sie den oben erwähnten Hack verwenden, warum erzeugt sie keine Warnung, wenn wir ein Programm mit ArrayList kompilieren?
Es würde nur eine Warnung geben, wenn Sie diese Klasse tatsächlich kompilieren . Aber nicht, wenn es bereits kompiliert wurde und Sie nur die Klassendatei verwenden. Tatsächlich haben Sie normalerweise nicht einmal die Quelle von ArrayList
.
3.) Gibt es einen besseren Weg als oben beschrieben?
Hängt davon ab, was Sie mit "besser" meinen. Ich habe die zwei Ansätze und die Vor- und Nachteile von jedem gezeigt.
Tags und Links java generics casting collections arraylist