# ArrayList casten



## unknown (10. Dez 2011)

Hallo 

Weiss jemand wie man ArrayLists casten kann?
Ich möchte folgendes tun, ein ArrayList<Object> in ein ArrayList<String> casten.

[Java] 
ArrayList<String> names = new ArrayList<String>();
names.add("it's");
names.add("just");
names.add("a");
names.add("test");
//		
ArrayList<Object> names2 = new ArrayList<Object>();
names2.add(names);
//		
ArrayList<String> names3 = new ArrayList<String>();
names3 = (ArrayList<String>) names2.get(0);
[/Java]


----------



## Gast2 (10. Dez 2011)

Das funktioniert so wie jeder andere cast auch 


```
ArrayList<Object> objects = new ArrayList<Object>();
ArrayList<String> strings = (ArrayList<String>)objects;
```


----------



## unknown (10. Dez 2011)

ok jetzt hab' ich folgendes gemacht:

```
ArrayList<String> names3 = new ArrayList<String>();
names3 = (ArrayList<String>)names2.get(0);
```
und bekomme eben diese Warnung:
"Type safety: Unchecked cast from Object to ArrayList<String>"

was soll noch gemacht werden?


----------



## tuttle64 (10. Dez 2011)

EikeB hat gesagt.:


> Das funktioniert so wie jeder andere cast auch
> 
> 
> ```
> ...




Nee, das funktioniert so nicht. Mit folgendem Trick geht es, da die ArrayList<Object> zu List<?> gecastet wird und dann zu einem String.


```
names3 = (ArrayList<String>)(List<?>)names2;
```


----------



## Gast2 (10. Dez 2011)

Naja ist doch auch klar.
Du hast eine Liste von Objekte, da kann alles mögliche drin sein. Jetzt will du daraus eine Liste von Strings machen, das kann dann natürlich krachen wenns auf einmal keine Strings sind. Da warnt der Compiler dich dann.


----------



## tuttle64 (10. Dez 2011)

EikeB hat gesagt.:


> Du hast eine Liste von Objekte, da kann alles mögliche drin sein. Jetzt will du daraus eine Liste von Strings machen, das kann dann natürlich krachen wenns auf einmal keine Strings sind. Da warnt der Compiler dich dann.




Deshalb geht der Compiler davon aus, dass beim Casten der Programmierer genau weiss, was er tut. Wenn er es nicht weiss, dann soll es aus krachen.


----------



## unknown (10. Dez 2011)

tuttle64 hat gesagt.:


> Nee, das funktioniert so nicht. Mit folgendem Trick geht es, da die ArrayList<Object> zu List<?> gecastet wird und dann zu einem String.
> 
> 
> ```
> ...



also du meinst so etwas?

```
names3 = (ArrayList<String>)(List<?>)names2.get(0);
```
ich bekomme eine Errormeldung: 
Cannot cast from List<capture#1-of ?> to ArrayList<String>


----------



## tuttle64 (10. Dez 2011)

just hat gesagt.:


> also du meinst so etwas?
> 
> ```
> names3 = (ArrayList<String>)(List<?>)names2.get(0);
> ...



Nein, names3 enthält die ganze Liste von names2, also geht names3.get(0). Sofern Du nur ein Element benötigst, geht auch


```
ArrayList<Object> objs = new ArrayList<Object>();
		
		objs.add("Hallo");
		objs.add("Welt");
		
		String s = (String)objs.get(0);
```


----------



## unknown (10. Dez 2011)

aber der folgende Code funktioniert ja auch nicht.

```
names3 = (ArrayList<String>)(List<?>)names2;
```

Meldung: Cannot cast from List<capture#1-of ?> to ArrayList<String>


----------



## tuttle64 (10. Dez 2011)

just hat gesagt.:


> aber der folgende Code funktioniert ja auch nicht.
> 
> ```
> names3 =names3 = (ArrayList<String>)(List<?>)names2;;
> ...



Sorry, mein Fehler: Es muss 

names3 = (ArrayList<String>)(ArrayList<?>)names2;

lauten.


----------



## Der Müde Joe (10. Dez 2011)

>names3 = (ArrayList<String>)(ArrayList<?>)names2;

bevor man so was schreibt, lässt man die Generics lieber gleich weg.


```
ArrayList<String> stringList =  (ArrayList)objectList;
```


----------



## irgendjemand (10. Dez 2011)

kann da Joe eigentlich nur zustimmen da der compiler TYPE-EREASURE anwendet ... *um angeblich abwärtskompatibel zu bleiben ...*

heißt : egal wie man auch rum-castet und wie sehr man generics in ein ander verschachtelt ... der compiler macht am ende einen RAW-type draus ...

so wird dann z.b. aus


```
List<List<Vector<HashMap<String, Object>>>>
```

nach dem anweden von Type Ereasure nur noch eine ganznormale


```
List
```

draus ...

daher ist es egal wie man da rumcastet ... der einzige der sich beschwert ist der compiler ... mit ner menge type-cast-warnings ...
wenn man aber innerhalb seines codes ganz genau weis was man macht und innerhalb des codes dafr sorgt das es nicht irgendwann zu fehlern kommt ... dann wird sich die VM auch nicht beschweren und die app ganz normal ablaufen ... egal ob ihr dann risiege verschachtelte casts macht und gleich von vornherein mit RAW-types arbeitet und die warnings ignoriert ...


----------



## unknown (10. Dez 2011)

und jetzt ist ein anders Problem aufgetaucht.

Ich benutze ArrayList "names" als einen Zwischenbehälter. Das heisst, jedes mal wenn names2 durch names gefüllt wird, sollen die Inhalte von names gelöscht werden, so dass ich es nochmals verwenden kann.

Und wenn ich jetzt die Methode clear() aufrufe, dann werden die Inhalte in names2 auch gelöscht!
habt ihr eine Lösung dafür?


```
ArrayList<String> names = new ArrayList<String>();
names.add("it's");
names.add("just");
names.add("a");
names.add("test");
		
ArrayList<Object> names2 = new ArrayList<Object>();
names2.add(names);
		
ArrayList<String> names3 = new ArrayList<String>();
names3 = (ArrayList<String>)names2.get(0);
names.clear();
System.out.print(names2.get(0));
```


----------



## irgendjemand (10. Dez 2011)

hat was mit referenzen und objekten zu tun ...

so wie du es jetzt machst verschiebst du immer nur referenzen ... hast aber im endeffekt nur ein objekt *vielleicht ist STRING nicht grad die beste wahl für ein beispiel -> stringpool und so*

was du tun musst ist die objekte kopieren ... so das du zwei objekte hast ... und nicht nur die referenzen ...


----------



## Der Müde Joe (10. Dez 2011)

1. Du machst eine List von Strings. names

2. Dann addest du die List in eine ArrayList -->names2 --> ArrayList mit einem Element, der Liste names

3 .Dann clearst du names.

Im Punkt 2 hast du genau diese Liste in die Liste 2 getan. Genau dieses Objekt. Das gleiche. Nun ist Leer...

EDIT:
hier ein Bsp:

```
import java.util.ArrayList;
import java.util.List;

public class XX {

	public static void main(String[] args) {
		
		Car car = new Car();
		car.name = "LADA";
		
		List<Car> cars = new ArrayList<Car>();
		cars.add(car);
		
		System.out.println(cars.get(0).name);
		
		car.name = "DACIA";
		
		System.out.println(cars.get(0).name);
	}

	
	static class Car {
		public String name;
	}
}
```


----------



## irgendjemand (10. Dez 2011)

ich denke das dir das problem nicht klar wird da du irgendwas in eine List<Object> adden willst ... und deine List<String> ist nunmal auch ein Object ... wesshalb der compiler das macht ...


du musst also nicht die List<String> selbst adden ... sondern druchiterieren und alle elemente der List<String> in die List<Object> kopieren


*gibts da nich sogar ne methode die das macht ?*


----------



## unknown (10. Dez 2011)

Ich will aber, dass der Inhalt von names wirklich in names2 kopiert wird. Eine Referenz bringt mir rein gar nichts.

Was wäre der richtige code, wenn ich eine Kopie möchte und keine Referenz. So Dass names2 von names völlig unabhängig wird.


----------



## irgendjemand (10. Dez 2011)

wie bereits erwähnt : erstmal anstatt die liste selbst zu adden deren inhalt durchgehen ...

geht mit foreach oder Iterator


----------



## AmunRa (10. Dez 2011)

Da gibt es keine vorgefertigte Methode, dies musst du selbst implementieren.

Mit einer schliefe über die Liste iterieren und jeden Eintrag selbst in eine Liste kopieren


----------



## Der Müde Joe (10. Dez 2011)

```
List<String> names2 =new ArrayList<String>(names);
```
oder

```
List<String> names2 =new ArrayList<String>();
```


```
names2.addAll(names);
```


----------



## unknown (10. Dez 2011)

Aber das bringt mir auch nichts, Wenn das 1. Element von names2 = das 1. Element von names etc. 

Was ich möchte ist folgendes:
das 1. Element von names2 was ja Objekte beinhalt, soll alle Elemente der names beinhalten (und keine Referenze).
und dann möchte ich names leeren und neue Namen einfügen, ohne dass sich das erstle Element von names2 dadurch ändern lässt


----------



## AmunRa (10. Dez 2011)

Probier doch mal aus was dir Der_Müde_Joe geschreiben hat, und wenn das nicht funktioniert, dann zeig ein bisschen Code was du hast und beschreib was du haben willst.

(Hatte ja ganz vergessen, dass die Listentypen in Java den Kopierkonstruktor haben (der macht meiner Meinung nach genau das was du moechtest))


----------



## Der Müde Joe (10. Dez 2011)

Ich verstehe das so nach deinen erklärungen:
(Immer schön eine neue List machen. sonst ist ja eben die gleiche Refenrenz)

```
List<String> names = new ArrayList<String>();
names.add("foobar");
names.add("foobar2");

List<Object> strangeThing = new ArrayList<Object>();
strangeThing.add(names);

names = new ArrayList<String>();
names.add("hello");
names.add("world");

strangeThing.add(names);
```


----------



## unknown (10. Dez 2011)

Sagen wir mal wir haben verschiedene Farben und jede Farbe hat einen ID:

So habe ich in jedem Element von ArrayList "farben" die entsprechende Informationen für jede Farbe.
Sprich im Element 0 habe ich die Infos für "white" im Element 1 die für "black" etc.


Also es würde mir nichts bringen wenn dass 1. Element von farbe ID wäre und das 2. Name etc. sondern sie sollen alle in einem Element sein


----------



## unknown (10. Dez 2011)

Ok das mit names = new ArrayList<String>(); würde funktionieren 
Aber wieso funktioniert es so und nicht mit clear()? Weil so ist ja der vorherige Inhalt auch nicht mehr vorhanden.


----------



## Der Müde Joe (10. Dez 2011)

Stell dir mal vor du hast ein Auto. (names)
und eine Garage (List<Object>)

Das Auto steht vor der Garage. Jetzt packst du ein Kasten Bier rein.
Das stellts du das Auto in die Garage. (names2.add(names))

In der Garage haste nun dein Auto mit dem Kasten Bier.

In der zwischenzeit wird das Bier im Auto getrunken. (clear())

Ob es nun in der Garage steht oder net...Das Bier ist weg.

Wenn du higegen ein neues Auto holst (new) und noch ein paar Flaschen Wein darin hast, und dies dann trinkst ist im anderen Auto das Bier immer noch da ;-)


----------



## unknown (12. Dez 2011)

eine weitere Frage:

wenn man zwei ArrayLists wie folgt hat:


```
ArrayList<String> test1 =  new ArrayList ArrayList<String>();
ArrayList<String> test2 =  new ArrayList ArrayList<String>();

test1 =  test2;
```

Dann sind beide ArrayLists von einander abhängig. sprich, wenn man im test2 etwas ändert, dann wird dieselbe Änderung auch im test1 vorgenommen.
Gäbe es eine Möglichkeit eine richtige Kopie von test1 zu machen und keine Referenz? So, dass man test2 ändern kann, ohne dass test 1 geändert wird?


----------



## AmunRa (12. Dez 2011)

ja


```
ArrayList<String> test1 =  new ArrayList ArrayList<String>();
//fuelle test1 mit werten
ArrayList<String> test2 =  new ArrayList ArrayList<String>(test1);
// test2 ist jetzt eine kopie von test1
```


wenn du jetzt zum Beispiel ein objekt aus test1 entfernst, dann ist es noch immer in test2 vorhanden.

ACHTUNG, die Objekte in der Liste sind aber noch immer die selben


----------



## unknown (12. Dez 2011)

tiptop. jetzt scheinen sie unabhängig von einander zu sein 
aber was meinst du mit:


> die Objekte in der Liste sind aber noch immer die selben


kannst du vielleicht ein Beispiel machen?


----------



## AmunRa (12. Dez 2011)

Hier bitte schoen ein kleines Beispiel


```
ArrayList<StringBuilder> test1 = new ArrayList<StringBuilder>();
		test1.add(new StringBuilder ("Hallo 1"));
		test1.add(new StringBuilder("Hallo 2"));
		
		ArrayList<StringBuilder> test2 = new ArrayList<StringBuilder>(test1);
		System.out.println("Groeße von Test1:"+test1.size());
		System.out.println("Groeße von Test2:"+test2.size());
		System.out.println();
		test1.remove(1);
		System.out.println("Groeße von Test1:"+test1.size());
		System.out.println("Groeße von Test2:"+test2.size());
		test1.get(0).append("jetzt wird bei test1 was hinzugefuegt");
		
		System.out.println(test2.get(0));
```

Ich musste um dies zu verdeutlichen StringBuilder verwenden und nicht String, da die Klasse String immutable sind und daher dort der Effekt nicht auffallen würde,


----------



## unknown (15. Dez 2011)

eine ähnliche Frage bezüglich der Objekten

wenn man so was hat:

```
BesipielObject a = new BesipielObject(); 
BesipielObject b = a;
```

b wird die gleiche Referenz haben wie a . sprich ändert man etwas in b, wird die Änderung in a auch übernommen.

kann man da auch ähnlich wie beim ArrayList eine richtige Kopie von a machen und keine Referenzierung?

//
und noch eine Frage, die nicht zum Topic passt, aber ich stelle sie jetzt mal 
Es gibt doch eine Alternative zum Import
Wenn ich beispielsweise "java.awt.Grapics;" nicht importiere, dann muss ich doch überall wo ich ein Type "Graphics" benutze, das Objekt "Grapics" aufrufen.
Wie sieht der entsprechende Befehl genau aus?


----------



## Michael... (15. Dez 2011)

just hat gesagt.:


> kann man da auch ähnlich wie beim ArrayList eine richtige Kopie von a machen und keine Referenzierung?


Wenn es sich um ein Objekt einer selbst definierten Klasse handelt muss man sich selbst darum kümmern. Manche Standard Objekte lassen sich mit clone() duplizieren.


just hat gesagt.:


> und noch eine Frage, die nicht zum Topic passt, aber ich stelle sie jetzt mal
> Es gibt doch eine Alternative zum Import
> Wenn ich beispielsweise "java.awt.Grapics;" nicht importiere, dann muss ich doch überall wo ich ein Type "Graphics" benutze, das Objekt "Grapics" aufrufen.
> Wie sieht der entsprechende Befehl genau aus?


Was für ein Object aufrufen? Keine Ahnung was genau Du meinst aber wenn man die Klasse oder das Package nicht in der import Anweisung angibt, muss im Code bei der Deklaration und Initialisierung immer den vollständigen Namen der Klasse - in diesem Fall "java.awt.Graphics" - angeben.


----------



## unknown (15. Dez 2011)

Michael... hat gesagt.:


> Wenn es sich um ein Objekt einer selbst definierten Klasse handelt muss man sich selbst darum kümmern. Manche Standard Objekte lassen sich mit clone() duplizieren.


und wie ginge das?


----------



## SlaterB (15. Dez 2011)

es gibt kein Objekt "Grapics", selbst ohne Tippfehler, du meinst doch wohl die Klasse,
was du in den Sätzen aber sagen willst bleibt verschlossen,

Import spart allein etwas Tipparbeit, 
ohne Import musst exakt eines tun: überall im Quelltext die Klasse lang schreiben wo sie vorher kurz stand,
absolut nichts sonstiges ändert sich

------

beim Kopieren von Objekten ist noch ein zusätzlicher Punkt zu beachten,
ob das Objekt a an sich dasselbe oder eine Kopie ist ist eine Frage,
die andere was mit intern referenzierten Objekten passiert


```
ArrayList<String> test1 =  new ArrayList ArrayList<String>();
ArrayList<String> test2 =  Kopie von test1
```
soll test2 zwar eine andere Liste sein, aber noch auf dieselben String-Objekte intern verweisen oder gar die Strings auch kopieren?
bei unveränderlichen Strings ist das relativ egal, wenn aber intern auf komplizierte Ressourcen wie Swing-GUI, Socket, Datenbank oder einfach die gesamte restliche Welt verwiesen wird, dann wird die Kopie schon sehr fraglich

alles kopieren geht z.B. mit Serialisierung
Deep-Copy von Java-Objekten  Der Informatik Student

der einfache Fall wird vielleicht von clone() geschafft
Object.clone() bzw wie klonen in Java? :: Fachsimpelei :: die-informatiker.net

üblicher ist aber doch ein Konstruktor, der manuell die nötigen Daten kopiert

> und wie ginge das?

selber im Internet lernen ist kein Weg?


----------

