Wie wird ArrayList intern in Java Collection Framework dargestellt?

8

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?

    
Mustafa Ujjainwala 01.04.2015, 15:08
quelle

2 Antworten

2

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

    
Sbodd 01.04.2015 15:31
quelle
1
  

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:

  • Du könntest das tun, wo s vom Typ Item[] ist, wie du oben gezeigt hast, und du erstellst Object[] und wirfst auf Item[]
  • Oder Sie können 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.

    
newacct 02.04.2015 07:56
quelle