Generics, arrays und classcastexception-Fehler
Ich denke, es muss etwas subtiler hier Los ist, weiß ich nicht. Betrachten Sie das folgende:
public class Foo<T> {
private T[] a = (T[]) new Object[5];
public Foo() {
//Add some elements to a
}
public T[] getA() {
return a;
}
}
Nehme an, dass deine main-Methode enthält die folgenden:
Foo<Double> f = new Foo<Double>();
Double[] d = f.getA();
Erhalten Sie eine CastClassException
mit der Meldung java.lang.Object
kann nicht gewirkt werden, um java.lang.Double
.
Kann mir jemand sagen warum? Mein Verständnis von ClassCastException
ist, dass es ausgelöst, wenn Sie versuchen zu casten eines Objekts zu einem Typ, der nicht gegossen werden. Das heißt, eine Unterklasse von denen es keine Instanz (Zitat der Dokumentation). z.B.:
Object o = new Double(3.);
Double d = (Double) o; //Working cast
String s = (String) o; //ClassCastException
Und es scheint, dass ich dies tun kann. Wenn a
war nur ein T
anstelle einer array - T[]
können wir a
und warf es, ohne ein problem. Warum arrays brechen?
Dank.
InformationsquelleAutor ntownsend | 2008-12-16
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wenn Sie diese version von der generischen Klasse Foo, dann für die member-variable
a
, der compiler ist im wesentlichen unter dieser Zeile:- und einbauen
T
mitDouble
um dies zu erhalten:Können Sie Umwandlung von Objekt zu Verdoppeln, damit die classcastexception-Fehler.
Update und Klärung: Tatsächlich, nach einigen test-code, der classcastexception-Fehler ist mehr subtil als diese. Zum Beispiel diese main-Methode wird funktionieren, ohne jede Ausnahme:
Das problem tritt auf, wenn Sie versuchen, zuweisen
f.getA()
auf eine Referenz des TypsDouble[]
:Dies ist, weil die Typ-Informationen über die member-variable
a
gelöscht ist zur Laufzeit. Generika nur Typ-Sicherheit am compile-Zeit (ich war irgendwie zu ignorieren, das in meinem ersten post). Das problem ist also nichtweil zur Laufzeit dieser code ist wirklich
Das problem tritt auf, wenn das Ergebnis der Methode
getA()
, die zur Laufzeit tatsächlich gibt einObject[]
zugeordnet ist, eine Referenz des TypsDouble[]
- diese Aussage wirft die classcastexception-Fehler, weil-Objekt kann nicht umgewandelt werden, zu Verdoppeln.Update 2: zur Beantwortung Ihrer letzten Frage "warum tun arrays brechen?" Die Antwort ist, weil die Sprache-Spezifikation nicht unterstützt generische array-Erstellung. Siehe diesen forum-post für mehr - , um rückwärts kompatibel, nichts ist bekannt über den Typ T zur Laufzeit.
für alle diejenigen, die Sie auch Lesen: angelikalanger.com/GenericsFAQ/FAQSections/...?
Der link oben hat einige gute Infos drin - könnte helfen, die ursprüngliche Frage-Fragesteller verstehen, mehr über type-erasure und was bekannt ist, werden die run-time vs. compile-Zeit
-1, weil die Erklärung ist unklar und unübersichtlich. Pandya ' s besser ist.
welcher Teil ist unklar???
InformationsquelleAutor matt b
Kann es einige kleine Fehler in @mattb Erklärung.
Den Fehler nicht
Ist es:
[L bedeutet, dass ein array. Das heißt, der Fehler ist, dass eine array von Objekten, die nicht Stimmen, um ein array von Double. Dies ist der gleiche Fall wie folgt:
Dies ist natürlich nicht erlaubt.
Für Ihr Problem zu erstellen typesafe-arrays, ist eine alternative, außer ein class-Objekt in der init und Arrays verwendet werden.newInstance:
Sie können nie "Besetzung" von A[] B[]. Betrachten wir zwei Klassen Obst und Apfel extends Frucht). So können Sie werfen vom Apfel zum Obst. Aber Sie können nicht umgewandelt von Apple[] Obst[]. Weil Sie können hinzufügen /alle/ Frucht (z.B. Orange) Frucht[], aber nur von Apple zu Apple[]
Oh wait, don ' T wissen, was ich Rede. Für zwei Klassen C1 < C2 (C2 zugeordnet werden können, C1) und eine generische Klasse G, C1[] < C2[] aber ! G<C1> < G<f2>. Das heißt, Apple - [] zugewiesen werden können, Obst[] aber List<Apfel> kann nicht zugeordnet werden, List<Obst - >....[Fortsetzung]
Aber wenn Sie versuchen, speichern Sie eine Orange in eine Frucht [], deren dynamische Typ ist der Apple[] bekommt man eine ArrayStoreException.
InformationsquelleAutor Miserable Variable
@matt b: vielen Dank für die Antwort! Sehr hilfreich ist.
Ich habe ein workaround für diejenigen, die interessiert sind: geben Sie dem getA-Methode eine initialisierte array zu füllen. So werden die Typ-info erhältlich ist.
Dann für Ihre main-Methode:
InformationsquelleAutor ntownsend