PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Java: Object [] nach String [] casten



axeljaeger
20-07-2003, 12:56
Hallo zusammen,
nach dem Lesen der Lektüre "Making Java Performance" von Sebastian Ritter (gibt's kostenlos bei www.bastie.de) bin ich bemüht, meine Javaprogramme auf Geschwindigkeit zu optimieren. Sebastian Ritter schreibt, es ist günstiger, eine ArrayList oder einene Vector in ein Array umzuwandeln, wenn man häufig auf die Eintrage zugreifen muss. Ich wollte jetzt ein kleines Testprogramm schreiben, das diese Aussage überprüft. Leider scheitere ich beim casten von Object [] auf String []. Der Code kompilier zwar ohne zu murren, aber ich bekomme eine Exception zur Laufzeit



import java.util.ArrayList;

class ArrayTest
{
public static void main(String [] args)
{

// Beispieleinträge
ArrayList arraylist = new ArrayList();
for(int i = 0; i < 10000; i++)
arraylist.add(String.valueOf(i));


// ArrayList direkt
long starttime = System.currentTimeMillis();
String tmp;
for(int i = 0; i < 10000; i++)
tmp = (String)arraylist.get(i);

System.out.println("Iterate over arraylist spend " + (System.currentTimeMillis() - starttime));


// ArrayList erst in Array kopieren
String [] array = (String [])(arraylist.toArray()); // <-- Das gibt eine Exception in thread "main"
// java.lang.ClassCastException: [Ljava.lang.Object;

starttime = System.currentTimeMillis();
for(int i = 0; i < 10000; i++)
tmp = array[i];
System.out.println("Iterate over array spend " + (System.currentTimeMillis() - starttime));

}
}


java-version sagt folgendes:



[axel@tecton Documents]$ java -version
java version "1.4.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-b92)
Java HotSpot(TM) Client VM (build 1.4.0-b92, mixed mode)
[axel@tecton Documents]$

anda_skoa
20-07-2003, 13:31
Dafür gibts ein den Containern eine überladenen Methode toArray(Object[]), die dann genau den Typ Array zurücklieftert, den man übergeben hat.

Genau den Array, wenn er lange genug ist



String[] strings = new String[arraylist.size()];
strings = arraylist.toArray(strings);


Ciao,
_

peschmae
21-07-2003, 16:33
hi,

ich seh den fehler auch nicht ganz

er tritt sowohl bei jdk 1.4.2 als auch mit gcj auf - also kein bug...

ich hab n bisschen bei mir in meinen Codes rumgeschaut: Casts von Object[] nach String[] finden sich an mehreren Orten und laufen auch Problemlos - aber nie einer mit ArrayLists

für die Arraylist verwende ich übrigens meist nicht eine so unflexible for schleife wie in deinem Beispiel sondern eher sowas:



ArrayList al = new ArrayList();

...

for (Iterator i = al.getIterator; i.hasNext();)
System.out.println(i.next());


MfG Peschmä

axeljaeger
21-07-2003, 16:57
Gut, ich möcht jetzt die For..Schleife auch nicht im Programm verwenden, es ging jetzt um ein kleines Testprogramm, ob sich das mit dem InEinArrayKopieren überhaupt lohnt. Bei einem Durchlauf lohnt es nicht, weil kopieren und einmal durchlaufen langsamer ist, als die ArrayList einmal durchzulaufen. Ab zwei Durchläufen müsste es sich lohnen

anda_skoa
21-07-2003, 17:57
Wie gesagt muss man nur die richtige Methode benutzen.

Der Cast schlägt fehl, weil die andere Methode eben kein String Array sondern eon Object Array erzeugt.

Vielleicht sieht man den Unterschied besser an einem Beispiel



String[] strings = new String[2]; // ein String Array
Object[] objects = new Object[2]; // ein Object Array
strings[0] = new String();
strings[1] = new String();

objects[0] = strings[0]; // geht, Strings ist eine Subklasse von Object
strings[0] = (String) objects[0]; // geht auch, das erste Element in objects ist ein String

strings = (String[]) objects; // geht nicht, objects ist ein Object Array, siehe Erzeugung


Die überladene toArray Methode benutzt den übergebenen Array sofern der groß genug ist, bzw erzeugt einen neuen Array und benutzt dabei die Typinformation des übergebenen Arrays.

Wenn man die Methode ohne Parameter benutzt, kann der Container nur sicher gehen, dass die Element Object Subklassen sind, also kann er nur ein Object Array erzeugen.

Mit den neuen Generics in 1.5 wird man dann typsichere Container machen können, die dann auch die richtigen Arrays proudzieren können.

Ciao,
_

peschmae
21-07-2003, 19:09
ah, jetzt ists klar :)

bei meinen beispielen wird immer ursprünglich ein String-Array erzeugt, das dann vorübergehend nach Object[] und anschliessend wieder explizit nach String[] gecastet wird.

Ich bin davon ausgegangen, das ein Array nicht "weiss" als was es erzeugt wurde und dass das Upcasten problemlos gehen sollte, sofern sämtliche Array-Inhalte Strings sind...

MfG Peschmä