Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
Hallo ich habe aktuell ein mir unverständliches Problem: ich möchte eine ArrayList in ein Array wandeln.
Java:
List<MyType> m_entries = new ArrayList<MyType>();
// Array mit 3 MyType-Instanzen befüllen (sind auch wirklich da)...
return (MyType[])m_entries.toArray(); // hier haut es leider eine ClassCastException rein
Warum passiert dies und wie kann ich das Problem umgehen?
Danke, das hat funktioniert!
- Da wird der Rückgabetyp von List#toArray(T[]) wohl auch über Generics festgelegt.
Was mich dabei aber noch interessieren würde ist, warum Java keinen Cast von Object[] zu MyType[] hinbekommt, auch wenn im Object-Array definitiv MyTypen stecken. Was ist hierfür die Erklärung?
in einem Object[] kann z.B. ein Integer-Objekt drinstecken,
warum sollte so ein Array ein MyType[] sein dürfen?
schlimm genug ist, dass es andersrum gar funktioniert:
Java:
public class Test
{
public static void main(String[] args)
{
String[] a = new String[1];
a[0] = "test";
Object[] o = a;
o[0] = new Integer(3000); // ArrayStoreException, es dürfen ja nur Strings rein,
// anderenfalls hätte man Probleme wenn man aus a[0] danach einen String lesen will
}
}
Entschuldige bitte - aber hier komme ich nicht mit... ???:L
Natürlich muss ein Object[] ein MyType[] sein dürfen, schießlich können in dem Object-Array nur MyType-Instanzen liegen.
Das es in meinem Fall auch wirklich so ist, weiß ich ja. - Daher wollte ich auch den Cast machen.
Da ich die Liste mit einem Generic deklariert habe, sollte die Liste auch wissen, was für ein Array zurückzugeben ist.
Wahrscheinlich ist dies aber nicht möglich, weil man eine Liste auch ohne Generic deklarieren kann und in diesem Fall MUSS die Liste ein Object-Feld zurückgeben. Und da man eine Methode nicht mit einer anderen überladen kann, welche einen anderen Rückgabetyp liefert, aber gleiche Funktionsparameter erfordert (in diesem Fall keinen), ist eine so praktische Methode eben nicht möglich.
=> Hier wäre eine Anwendungspflicht für Generics sicherlich die sauberere Lösung.
Die Frage besteht aber nach wie vor: warum funktioniert der Cast nicht?
- Ich kann ja ohne Probleme ein Component-Object in einen JButton casten. (natürlich nur, wenn auch wirklich ein JButton drin steckt!)
eine einzelne Variable/ ein Objekt ist was anderes als ein Array, schau dir diesen Code an:
Java:
Object o = new JButton();
JButton b = (JButton) o;
o = new Integer(300);
o.toString();
b.addActionListener(..);
mit der o-Variablen kann man nicht viel machen außer Object-Methoden aufzurufen und vielleicht andere Objekte zuzuweisen,
was dann der b-Variable herzlich egal ist, kein Fehler möglich,
anders ist das beim Object[]
Java:
Object[] o = new Object[1];
o[0] = new JButton();
JButton[] b = (JButton[]) o; // hier schon Exception, aber angenommen das ginge,
// zu diesem Zeitpunkt sind ja auch nur JButtons drin, falls das ein Kriterium wäre (ist es nicht)
// o = new Object[2];
o[0] = new Integer(300);
JButton b = b[0]; // was steht in b[0]?
in Zeile 11 gäbe es eine Exception, denn b und o sind ja noch dasselbe eine Array-Objekt,
an Position 0 steht dort ein Integer, wie soll das JButton sein?
erst an dieser Stelle eine unvermutete Exception zu werfen ist nicht sinnvoll,
auch nicht den 'Cast' nur dann zu erlauben, falls danach kein gefährlicher Code kommt oder so,
also ist die Konsequenz:
lieber gleich den Cast verhindern, das geht einfach nicht (auch wenn in die andere Richtung leider erlaubt, siehe vorherigen Post)
------
würde die auskommentierte Zeile 8 ausgeführt, wäre die Situation ähnlich wie bei der einzelnen Object-Variable:
dem b-Array wäre es egal was im nun separaten anderen o-Array passiert, aber ein Array kann nunmal in mehreren Variablen stecken
ein Cast soll auch keine automatische Kopie eines Objektes/ eines Arrays erstellen, das wäre eine ganz andere Aufgabe
Hier steckt kein JButton drin hier muss die Component ein JButton sein, damit der Cast funktioniert.
Grundsätzlich kann man mittels einer Variable die als Object[] deklariert wurde, aber auf ein MyType[] referenziert, dessen Inhalt per Cast wieder durch eine als MyType[] deklarierten Variable referenzieren.
Wenn Du aber die toArray() Methode ohne Generics nutzt wird hier eine Object Array erstellt, zwar gefüllt mit MyType Objekten aber eben kein MyType Array. Die Methode weiss ja gar nicht was für ein Array zu haben willst. Daher gibt es ja die zweite generische Methode mit der man den Rückgabetyp definieren kann.
Der erste Fall wäre so, als wenn Du die Bierflaschen aus dem Kasten nimmst und in einen Eimer stellst und versuchst am Pfandautomaten den Eimer mit den Bierflaschen zurückzugeben.