Warum kann ich ein Array eines generischen Typs nicht erstellen?

8

Kurz gesagt, das wird nicht kompiliert:

%Vor%

Liegt es an Problemen mit der Rückwärtskompatibilität oder ist es etwas Grundlegendes im Sprachdesign, das das verhindert?

    
pgsandstrom 25.07.2012, 12:26
quelle

5 Antworten

5

Die untere Zeile besagt, dass die Klasse, die das Array darstellt, den Komponententyp kennen muss. Daher die Methode für das Klassenobjekt:

%Vor%

Also, wenn du es versuchen würdest:

%Vor%

Bei der Kompilierung ist es offensichtlich, dass wir den Typ nicht kennen, da es sich um einen generischen Parameter handelt. Zur Laufzeit kennen wir den Typ aufgrund von Typlöschung nicht. So ist das Instanziieren des Arrays unmöglich.

Stellen Sie sich die obige Aussage als gleichwertig vor:

%Vor%

Und wegen der Art des Löschens können wir die Klasse von A zur Laufzeit nicht bekommen.

Es wurde gefragt, warum der Compiler nicht auf Object [] oder Number [] oder so etwas reduzieren soll?

Dies liegt daran, dass je nach Komponententyp eine andere Klasse zurückgegeben wird. Also:

%Vor%

sind nicht dieselbe Klasse. Insbesondere die Methode "getComponentType ()" für die Klasse würde verschiedene Werte zurückgeben.

Wenn Sie es also auf Object [] anstelle von A [] reduzieren, erhalten Sie tatsächlich nicht etwas vom Typ A [] zurück, sondern Sie erhalten Objekt [] zurück. Object [] kann nicht auf Integer [] übertragen werden und führt zu einer ClassCastException.

    
Matt 25.07.2012, 12:59
quelle
5

Geben Sie löschen ist das Wort, das Sie suchen. Es bedeutet im Grunde, dass die generischen Informationen zur Kompilierungszeit gelöscht werden. Der Hauptgrund dafür ist die Rückwärtskompatibilität. Ältere Programme sollten immer noch auf der neuen Java Virtual Machine laufen.

    
dvberkel 25.07.2012 12:28
quelle
1

Dies funktioniert nicht für den gleichen (oder fast den gleichen) Grund, dass new A() nicht funktionieren kann: Sie erwarten, dass der Compiler den Laufzeittyp von A kennt, den er eindeutig nicht kennen kann. Dieses würde funktionieren, wenn Java Generics wie C ++ - Templates wären, wo für jede Instantiierung des Templates mit A neuer Code generiert wird.

    
Marko Topolnik 25.07.2012 12:34
quelle
1

In Java ist das Typsystem für Arrays und Generics inkompatibel. Es gibt zwei Hauptbereiche der Diskrepanz: dynamische vs statische Typüberprüfung und Kovarianz .

Generics werden statisch überprüft, das heißt, der Compiler stellt sicher, dass die Typdefinitionen kohärent sind. "Type Erasure" war ein Kompromiss, um die Rückwärtskompatibilität in der JVM zu gewährleisten. Nach der Kompilierung ist die generische Typdefinition nicht mehr verfügbar. Z.B. Liste wird zu Liste.

Im Gegensatz dazu werden Arrays dynamisch typisiert. Betrachten Sie das folgende Beispiel:

%Vor%

Kovarianz ist die Vererbungsbeziehung eines Containers basierend auf dem Inhalt. Gegeben sind die Typen A, B und ein Container C, wenn B isAssignableFrom (A) = & gt; C isAssignable C.

Arrays in Java sind im vorherigen Beispiel kovariant, vorausgesetzt, Class<Object>.isAssignableFrom(Class<String>) => Object[] is assignable from String[]

Im Gegensatz dazu sind generische Typen in Java nicht kovariant. Verwenden Sie das gleiche Beispiel:

%Vor%

Angesichts der Typlöschung der Generika-Implementierung gehen Typinformationen in der Übersetzung verloren, und daher wäre die dynamische Typprüfung beeinträchtigt, wenn Sie ein Array eines generischen Typs erstellen könnten.

Lesen Sie weiter die Komplikationen und Auswirkungen dieser Probleme: Arrays in Java Generics

    
maasg 25.07.2012 13:16
quelle
0

Ja, es gibt einen fundamentalen Grund, der darauf hinausläuft, Löschen zu tippen .

Betrachten Sie das folgende Snippet:

%Vor%

Verwandte Frage:

aioobe 25.07.2012 12:28
quelle