# ArrayList Referenz



## Kris (28. Feb 2009)

Hallo

ich habe ein kleoines Verständnisprolem.

Wenn ich in einem Objekt eine Variable des Typs ArrayList erstelle, und diese dann an ein Objekt weiter gebe, dann kann das Objekt diese bearbeiten.
Mit add klappt alles super. Wenn aber eine neue ArrayList des selben Typs erstellt wird und diese dann der übergebenen Variable zugewiesen wird, dann werden die Werte nicht übergeben.

Ein kleines Beispiel siehe unten. Gibt es dafür eine Lösung bzw. könnte mir jemand erklären warum dies der Fall ist?

[HIGHLIGHT="Java"]package test;

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


/**
 * @author Kris
 *
 */
public class Main {

	private List<String> strings;

	/**
	 * 
	 */
	public Main(){
		strings =new ArrayList<String>();
		gebeAus();
		new Child(this, strings).aendereStrings();
		gebeAus();
		new Child(this, strings).erneuere();
		gebeAus(); // keine Ausgabe, da die Werte verlorengegangen sind
	}

	/**
	 * 
	 */
	public void gebeAus(){
		for(int i=0;i<strings.size();i++){
			System.out.println(strings.get(i));
		}
	}
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		new Main();
	}

}[/CODE]


```
package test;

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

/**
 * @author Kris
 */
public class Child {

	private List<String> strings;
	private Main main;

	/**
	 * @param main
	 * @param strings
	 */
	public Child(Main main, List<String> strings) {
		this.main = main;
		this.strings = strings;
		for (int i = 0; i < 20; i++) {
			strings.add("Test" + i);
		}
	}

	/**
	 * 
	 */
	public void aendereStrings() {
		for (int i = 0; i < strings.size(); i++) {
			strings.set(i, strings.get(i) + "A");
		}
		main.gebeAus();
	}

	/**
	 * 
	 */
	public void erneuere() {
		List<String> neueListe = new ArrayList<String>();
		for (int i = 0; i < 20; i++) {
			neueListe.add("ZZ" + i);
		}
		strings = neueListe;
	}
}[/HIGHLIGHT]
```


----------



## Ravendark (28. Feb 2009)

Wenn du in Java eine Referenz als Parameter übergibst, dann kannst du zwar das worauf die Referenz zeigt verändern (sprich den Inhalt des Objektes worauf die Referenz zeigt), aber wenn du die Referenz an sich änderst, hat das keine Auswirkungen auf das Objekt, mit der diese Methode aufgerufen wird.
Liegt daran dass in Java immer nur eine Referenzkopie an die Methode übergeben wird.


----------



## Kris (28. Feb 2009)

Also veränder man mit 

[HIGHLIGHT="Java"]strings = neueListe;[/HIGHLIGHT]

nur die Referenz.

Das Objekt muss man dann so bearbeiten?

[HIGHLIGHT="Java"]neueLsite.removeAll(neueListe);
strings.addAll(neueListe);[/HIGHLIGHT]


----------



## Ravendark (28. Feb 2009)

Kris hat gesagt.:
			
		

> Also veränder man mit
> 
> [HIGHLIGHT="Java"]strings = neueListe;[/HIGHLIGHT]
> nur die Referenz.


Damit weist du der Referenzvariablen strings die Referenz neueListe zu. D.h strings beinhaltet jetzt eine Referenz zu dem Objekt, welches neueListe referenziert.


----------



## Marco13 (28. Feb 2009)

Kris hat gesagt.:


> ```
> neueLsite.removeAll(neueListe);
> strings.addAll(neueListe);
> ```


Müßte so passen...


----------



## Spacerat (28. Feb 2009)

Hier wird ausschliesslich die Liste von "Child" erneuert. Die Referenz auf "main.strings" geht bei "child.strings = neueListe" verloren. "Child.erneuere()" müsset ungefähr so aussehen.[HIGHLIGHT="Java"]public void erneuere()
{
  strings.clear();
  for(int i = 0; i < 20; i++) {
    strings.add("ZZ" + i);
  }
}[/HIGHLIGHT]


----------



## beastofchaos (21. Jul 2011)

Ich weiß - älteres Thema, aber besser als neuer Thread 

Ich habe eine Methode, die ursprüglich eine ArrayList<Integer> übergibt und als Parameter einen String erwartet. Die Methode splittet den String und macht daraus Integers, die in die ArrayList verschoben. Leider muss ich jetzt aber außerhalb der Methode wissen, ob es auch erfolgreich war. Deswegen ist nun die ArrayList ein Parameter und es wird ein boolean übergeben.

Selbes Problem: Die Änderungen durch add werden nicht als Referenz übergeben. Bisher war hier die Ausweichmöglichkeit, dass in der Methode die globale Variable direkt verändert wird und nicht nur ein Parameter, doch bei mir sind es zwei getrennte Klassen, wo ich es lieber mit einem Paramet schaffen will 

Hier die Methode, und wo sie einmal z.B. aufgerufen wird:


```
private void actualize(boolean close){
        if (!Sound.getArray(main.sounds, textSounds.getText())){
            return;
        }
        ...
```


```
public static boolean getArray(ArrayList<Integer> array, String string){
        array = new ArrayList<Integer>();                                   // Geht mit und ohne nicht
        ...
        array.add(Integer.parseInt(string));                                // Per While-Schleife wird diese Stelle öfters ausgerufen
        ...
        return true;                                                        // Nur ein möglicher Ausgang
    }
```

Hab ich schon mit Debugger durchlaufen lassen. Die Methode macht, was sie soll, aber wenn ich aus der Methode wieder rausgehe, ist alles beim alten :/

Freu mich über schnelle Antworten 
Gruß, Thomas


----------



## ARadauer (21. Jul 2011)

```
array = new ArrayList<Integer>();                                   // Geht mit und ohne nicht
```
das ist genau der Punkt. Dein Aufrufer zeigt auf Liste A und jetzt machst du eine Liste B und fügst dort ein. Dein Aufrufer sieht aber immer noch A.
Warum geht es ohne nicht, füg doch einfach in die übergebene Liste ein? Wenn das nicht funktioniert liegt der Fehler wo anders, zb Sound.getArray

Wobei ich hier schon sehe, dass du dir vielleicht nochmal Objekte im Allgemeinen ansehen solltest.

Zeig mal Sound.getArray


----------



## beastofchaos (21. Jul 2011)

Ich dachte mir auch shcon, dass die Referenz wohl entfällt, wenn ich den Konstruktor aufrufe... :/ Glaubst, ich krieg das mit clear() hin? Sonst werd ich halt einfach vor dem Methodenaufruf von getArray() schon clear() aufrufen.

Ok, mit clear() funktioniert es 
Hier die Methode vollständig:


```
public static boolean getArray(ArrayList<Integer> array, String string){
        array.clear();
        boolean lastItem = false;
        boolean continueWhile = true;
        while (continueWhile){
            int cutter = 3;                                                     // Nur dreistellige Zahlen möglich
            try{
                if (lastItem){
                    array.add(Integer.parseInt(string));
                    //continueWhile = false;
                    break;
                }
                
                boolean testInt = false;
                try{
                    Integer.parseInt(string.substring(0, 1));
                }catch(NumberFormatException tempExc){
                    testInt = true;
                }
                
                try{
                    Integer.parseInt(string.substring(cutter, cutter + 1));
                    testInt = true;
                }catch(NumberFormatException tempExc){}
                
                try{
                    Integer.parseInt(string.substring(cutter + 2, cutter + 3));
                    testInt = true;
                }catch(NumberFormatException tempExc){}
                
                if (testInt){
                    throw new NumberFormatException();
                }
                
                array.add(Integer.parseInt(string.substring(0, cutter)));
                string = string.substring(cutter + 3, string.length());
                if (lastItem){
                    continueWhile = true;
                }
                else if(string.length() < 9){
                    lastItem = true;
                }
                
            }catch(NumberFormatException exc){
                JOptionPane.showConfirmDialog(null, "Schema: dreistellige Zahl + ' ' + '-' + ' '" + '\n' + "Beispiel: 002 - 100 - 060 - 062" + '\n' + 
                                              "Standardersatzwerte: Ton = 060, Lautstärke = 080", "Falsche Definition von Ton oder Lautstärke", JOptionPane.DEFAULT_OPTION);
                return false;
            }
        }
        return true;
    }
```

Damit ihr Bescheid wisst, mein Programm ist eine Art Stoppuhr. Weil mein Compi keine hat, aber ich selbst mal schnell gemacht  Wie das so ist, will man immer mehr dazu machen. Jetzt hab ich noch einen Sound eingebaut, der abgespielt wird, wenn man eine angegebene Zeit erreicht hat. Das gibt man in einem JTextfield an, mit dem Schema "dreistellige Zahl, Leertaste, Minus, Leertaste,..." 
Das ich da mehrere try-Strukturen hab, soll jetzt nicht wundern, denn ich will schauen, dass da keine Zahlen sind. Wenn Zahlen sind, wird der catch-Block nicht aufgerufen und die Variable "testInt" wird auf true gesetzt. Am Ende wirft er bei testInt = true eine Exception  Aufwendig, unschön, aber besser gehts nicht 

Gru und Dankeschön, Thomas


----------

