Warum darf ich ein generisches Array als Instanzvariable deklarieren?

8

Mir ist völlig klar, dass generische Arrays nicht wie solche instanziiert werden können:

%Vor%

Dies führt zu einem Fehler:

%Vor%

Also, warum darf ich eine Instanzvariable deklarieren, die ein generisches Array ohne Fehler ist?

%Vor%     
grimetime 12.03.2012, 07:30
quelle

2 Antworten

4

Prinzipiell ist der Kommentar von Joachim Sauer bereits Ihre Antwort, ich möchte sie jedoch etwas genauer erläutern.

Sun (Oracle) kennt ein Phänomen namens Memory-Pollution, das immer dann auftritt, wenn ein generischer Variablenzeiger auf ein typinkompatibles Objekt zeigt. Dies kann zum Beispiel mit dem folgenden Code erzwungen werden:

%Vor%

Sie werden offensichtlich ClassCastExceptions sehen, sobald Sie anfangen, mit diesem Code zu arbeiten. Das war vollkommen in Ordnung für Sun, wenn es um Generics ging, denn Sie erhalten eine obligatorische Warnung RawType / Unchecked Conversion. Wann immer diese Warnung ausgegeben wird, wissen Sie, dass Sie Code haben, der nicht zu 100% typgeprüft ist und Speicherverschmutzung verursachen kann.

Das generelle Designprinzip in Generics ist, dass alle möglichen Speicherverschmutzungen durch solche Warnungen angezeigt werden. Aus diesem Grund ist die Erstellung von generischen Arrays verboten. Angenommen, es war nicht, hier ist, was passieren könnte:

%Vor%

Sie werden ohne Warnung eine Speicherbelastung haben und aus Kompatibilitätsgründen kann keine Warnung generiert werden. Aus diesem Grund hat Sun entschieden, Arrays generischer Typen zu verbieten. Es können jedoch Variablen deklariert werden, weil Sie dort Ihre ungeprüfte Konvertierungswarnung erhalten und dies ist alles, was Sun wollte: eine Warnung, wenn eine Verunreinigung auftreten könnte.

    
Jonathan 12.03.2012, 08:18
quelle
2

Weil der Compiler und / oder das JIT in der Lage sein müssen, die generischen Typen abzuleiten.

Wenn Sie versuchen, eine Instanz von Entry<K, V>[] zu erstellen, kann der Compiler die Typen K und V nicht ableiten, so dass Sie das eigentliche Objekt nicht erstellen könnten (was bedeutet, dass der Compiler das Objekt nicht finden kann) rechter Konstruktor).

Aber wenn Sie ein Mitglied vom Typ Entry<K, V>[] haben, ist es nur ein Verweis auf einen generischen Typ.
Der richtige Typ wird abgeleitet, wenn er verwendet wird, entsprechend dem tatsächlichen Typ, der ihm zugewiesen wird. Und da es sich auf einen tatsächlichen Typ bezieht, wird die gesamte Methode, die anc-Konstruktoren aufruft, durch den referenzierten Typ bestimmt.

    
Yochai Timmer 12.03.2012 07:41
quelle