[Java] Generics Mechanik -- CastClassException bei Arrays primitiver Datentypen

T

Tersus

Gast
Guten Tag,

folgender Quelltext:

Code:
@SuppressWarnings("unchecked")
public static <T> void TesteTypAufArray(T array){

	if(array.getClass().isArray()){
		int arraybereite = ((T[]) array).length;

		System.out.println(arraybereite);

	}else{

		throw new IllegalArgumentException("Kein Array!");

	}
	
}

Wenn ich der Klassenmethode TesteTypAufArray(new int[1]) eindimensionale Arrays primitiver Datentypen übergebe, folgt die CastClassException [I cannot be cast to [Ljava.lang.Object;".
Das Array eines primitiven Datentypen kann nicht auf ein Array eines komplexen Datentypen gecastet werden.

1. Wieso versucht die JVM, auf [Ljava.lang.Object zu casten? Dieser Typ kommt doch nirgends vor!

Unser Generic T ist vom Typ des Übergabeparameters. In diesem Fall vom Typ [I, also einem Array, welches Elemente des primitiven Datenyps int beinhaltet.

Nach Wahrheit der If-Abfrage handelt es sich definitiv um ein Array. Wie sagen wir dem Compiler, dass er eine Variable vom Typ Array vor sich hat? Wir casten auf ein Array. Das geht nur mit ((T[]) array).
Nun können wir die Methoden und Attribute eines Arrays aufrufen, wie unter anderem length.
Sobald das jedoch gemacht wird, folgt der Wurf der hier erwähnten Ausnahme.

2. Wie kann ich die Methode sicher gegenüber primitiven Datentypen machen?
Selbst Arrays von primitiven Datentyen sind Instanzen von Object.

Meine Lösung ist im Moment wirklich nur die Überprüfung der Zeichenketten von getClass().toString();. Also Überprüfen, ob die Teilzeichenkette Ljava.lang.Object im Übergabeparameter vorkommt.
 
1.
Weil alle Klassen von Objekt erben, ist Objekt wohl die generischte Klasse, die es überhaupt geben kann.
Klingt also sehr sinnvoll, was die JVM versucht.

2.
prüf bei den primitiven Datentypen (außer String) mit instanceof und caste dann gleich zum richtigen Typ

D.h. wenn instanceof Object[] fehlschlägt, prüfst du auf ein Array primitiven Typs. Falls alle Prüfungen fehlschlagen, könnte aber auch "null" übergeben worden sein. Das solltest du früher noch prüfen.

http://stackoverflow.com/a/2725555/1257591
 
Zuletzt bearbeitet:
Redirion schrieb:
1.
Weil alle Klassen von Objekt erben, ist Objekt wohl die generischte Klasse, die es überhaupt geben kann.
Klingt also sehr sinnvoll, was die JVM versucht.

Das ist überhaupt keine Begründung. Generics sind Templates und werden zur Laufzeit in den entsprechenden Typen umgewandelt. Deshalb nimmt T ja genau den Typ an, den ich übergebe. In diesem Fall, wie schon erwähnt, ein Array eines primitiven Datentyps.

Redirion schrieb:
2.
prüf bei den primitiven Datentypen (außer String) mit instanceof und caste dann gleich zum richtigen Typ

D.h. wenn instanceof Object[] fehlschlägt, prüfst du auf ein Array primitiven Typs. Falls alle Prüfungen fehlschlagen, könnte aber auch "null" übergeben worden sein. Das solltest du früher noch prüfen.

Ich kann nicht mit instanceof Object[] prüfen, da diese Prüfung nur eindimensionale Arrays berücksichtigt. Ich möchte jede Dimension von Arrays berücksichtigen können.

Außerdem: Wenn man einer generischen Methode ein Array eines primitiven Datentyps übergibt, ist mir keine Möglichkeit bekannt, wie ich typsicher auf die primitiven Elemente des Arrays zugreifen kann. Casten geht ja anscheinend nicht.
 
Tersus schrieb:
Das ist überhaupt keine Begründung. Generics sind Templates und werden zur Laufzeit in den entsprechenden Typen umgewandelt. Deshalb nimmt T ja genau den Typ an, den ich übergebe. In diesem Fall, wie schon erwähnt, ein Array eines primitiven Datentyps.

Das ist die logische Sicht. Die technische Sicht ist, dass T zur Laufzeit den Typ Object annimmt und beim Zugriff ein impliziter Cast auf den gewünschten Typ stattfindet. Stichwort für Google ist Type Erasure, was für Java's Generics eingesetzt wird. Deshalb sagt man manchmal auch, Java hätte keine "echten" Generics, was imo etwas zu hart ausgedrückt ist. Sie haben aber in der Runtime kein eigenes Konzept dafür wie es beispielsweise .NET hat.
 
Zuletzt bearbeitet:
Zurück
Oben