Skip to main content

So lassen sich Java Arrays kopieren



Java Arrays kopieren oder klonen….
Was heißt das eigentlich?

Eine Kopie ist eine Reproduktion bzw. die Nachbildung eines Originals.

  • Somit ist jede Fotographie – die Abbildung einer bestimmten optischen Wirklichkeit, zu einem festen Zeitpunkt.
  • Die Kopie einer Buchseite ist das optische Abbild dieser spezifischen Buchseite – auch zu einem festen Zeitpunkt.

Wichtig in diesem Zusammenhang ist.
Die Kopie zerstört niemals das Original.
Kopie und auch das Original bleiben beim Kopieren immer erhalten.

Nehmen wir diesen letzten wichtigen Gedanken einmal mit.
Und lass uns einmal gemeinsam prüfen, wie du Java Arrays kopieren kannst.

Also dann mal los.

Java Arrays kopieren durch Umswitchen.

Und zwar durch Umswitchen der Referenzvariablen.
a=b;
Du weißt was ich meine.

Geht das – oder nicht?
Was denkst du?

Am besten wir schauen uns ein Beispiel dazu an.

public class ArraysKopieren {

	public static void main(String[] args) {
		int arrayEins [] = new int [3];//im ersten Array können 3 Integerwerte gespeichert werden
		int arrayZwei [] = new int [3];//das zweite Array hat ebenfalls eine Länge von 3
	}
}

Ich habe zwei Java Arrays angelegt, arrayEins und arrayZwei.
Beide Arrays können drei Integerwerte aufnehmen bzw. speichern.

Ich fülle das erste Array einfach einmal mit drei Werten.

public class ArraysKopieren {

	public static void main(String[] args) {
		int arrayEins [] = new int [3];
		int arrayZwei [] = new int [3];
		
		arrayEins[0]=2;//Im Fach Null steckt jetzt der Wert 2
		arrayEins[1]=3;//Im Fach mit dem Index 1 - steckt jetzt der Wert 3
		arrayEins[2]=4;//Im Fach 2 steckt jetzt der Wert 4
	}
}

Jetzt lass uns umswitchen.
Dazu weist du der Referenzvariablen arrayZwei den Wert von arrayEins zu.
So wie hier:

public class ArraysKopieren {

	public static void main(String[] args) {
		int arrayEins [] = new int [3];
		int arrayZwei [] = new int [3];
		
		arrayEins[0]=2;
		arrayEins[1]=3;
		arrayEins[2]=4;
		
		arrayZwei=arrayEins; //ArrayZwei bekommt die Speicheradresse aus arrayEins zugewiesen
	}
}

Die „arrayZwei“ Referenzvariable bekommt den Wert der ersten Referenzvariable zugewiesen.
Und somit stecken jetzt auch im zweiten Array die gleichen Werte.

Oder doch nicht?
Lass es uns einmal überprüfen.
Und zwar mit zwei For-Schleifen, welche jetzt beide Arrays durchlaufen sollen.

public class ArraysKopieren {

	public static void main(String[] args) {
		int arrayEins [] = new int [3];
		int arrayZwei [] = new int [3];
		
		arrayEins[0]=2;
		arrayEins[1]=3;
		arrayEins[2]=4;
		
		arrayZwei=arrayEins; 
		
		//Forschleife durchläuft das erste Array
		for (int i=0;i<arrayEins.length;i++){
			System.out.println(arrayEins[i]);
		}
	
		//Forschleife durchläuft das zweite Array
		for (int i=0;i<arrayZwei.length;i++){
			System.out.println(arrayZwei[i]);
		}
	}
}

Kopier dir den Code oder schreib diesen ab.
Klicke auf „RUN“ und schau, was passiert.

Es werden beide Arrays durchlaufen und jeweils die selben Werte ausgegeben.
Du hast kopiert, oder?

Nein!
Denn ich verändere jetzt einfach mal ein Fach.
Im Fach 1 stecke ich jetzt die Zahl 9999.

public class ArraysKopieren {

	public static void main(String[] args) {
		int arrayEins [] = new int [3];
		int arrayZwei [] = new int [3];
		
		arrayEins[0]=2;
		arrayEins[1]=3;
		arrayEins[2]=4;
		
		arrayZwei=arrayEins; 
		
		//Forschleife durchläuft das erste Array
		for (int i=0;i<arrayEins.length;i++){
			System.out.println(arrayEins[i]);
		}
	        arrayEins[1]=9999;//Im Fach ist jetzt ein anderer Wert

		//Forschleife durchläuft das zweite Array
		for (int i=0;i<arrayZwei.length;i++){
			System.out.println(arrayZwei[i]);
		}
	}
}

Klicke nochmal auf „RUN“ und schau – was passiert.

Und was ist geschehen?
Es steckt jetzt automatisch im zweiten Array auch die Zahl 9999.

Tritt dieses Phänomen bei Kopien auf?

Das wäre in etwa so:

  1. Du kopierst eine einzelne Seite eines Buches.
  2. Später nimmst du dir das Original-Buch und malst einen Strich auf die entsprechende Original-Seite.
  3. Und wie von Geisterhand, würde dann automatisch der Strich auch auf der Kopie sein.

Das wäre sicherlich total cool und der richtige Stoff für ein großartiges Youtube Video.
Aber eine Kopie hättest du nicht gemacht.

Denn die Kopie ändert sich nicht, wenn sich das Original ändert.
Kopie und Original haben später keine Verbindung mehr zu einander.
Sie stehen also auch nicht in einem Ursache-Wirkungs-Verhältnis.

Aber unser scheinbar kopiertes Array steht genau in diesem Verhältnis.
Also was ist passiert?

Als wir die zwei Referenzvariablen und beide Arrays anlegten – war die Welt noch in Ordnung.


Wir hatten zwei Variablen und jede zeigte auf ein separates Array im Speicher.

Als wir dann die Variable „arrayZwei“ umgeswitcht haben, zeigte diese dann ebenfalls auf das erste Array.

Auf das zweite Array zeigte somit keine Variable mehr.
Und dieses Array war dann Futter für den Garbage Collector.
Zu deutsch: Das zweite Array wurde zerstört.

Und somit wird eines ganz deutlich:

Durch Umswitchen können Java Arrays nicht kopiert werden.

Java Arrays mit einer for-Schleife kopieren.

Sollte das funktionieren?
Lass uns es ausprobieren.

Was brauchst du dazu?
Ich stelle es mir so vor:

  • Wir legen zwei Arrays an.
  • Und dem ersten Array weisen wir Werte für jedes Fach zu.
  • Eine For-Schleife durchläuft das zweite Array.
    Und diese Schleife speichert die Werte aus den Fächern des ersten Arrays im jeweiligen Fach des zweiten Array.
  • Zur Überprüfung legst du dann eine zweite For-Schleife an.
    Und diese zweite Schleife durchläuft das zweite Array und gibt die Werte zurück.

So sieht der Java Code dazu aus.

public class ArraysKopieren {

	public static void main(String[] args) {
		int arrayEins [] = new int [3];//im ersten Array können 3 Integerwerte gespeichert werden
		int arrayZwei [] = new int [3];//das zweite Array hat ebenfalls eine Länge von 3
		
		arrayEins[0]=2;//Im Fach Null steckt jetzt der Wert 2
		arrayEins[1]=9999;//Im Fach steckt der Wert 9999
		arrayEins[2]=4;//Im Fach 2 steckt jetzt der Wert 4
	
		//Forschleife durchläuft das zweite Array und speichert Werte aus ersten Array
		for (int i=0;i<arrayZwei.length;i++){
			arrayZwei[i]=arrayEins[i];
		}
		
		//Forschleife gibt Werte des zweiten Arrays aus
		for (int i=0;i<arrayZwei.length;i++){
			System.out.println(arrayZwei[i]);
		}
		
	}
}

Klicke auf „RUN“!
Und läuft?

Läuft das Teil aber noch – wenn du die Fächerwerte aus dem ersten Array änderst?
Oder anders gefragt: Was passiert, wenn jetzt im Fach 1 wieder die 3 steckt.
Hat das Auswirkungen auf das zweite Array?

Na klar….
Denn der Code, so wie dieser hier dasteht – lässt ja immer wieder die Werte neu speichern.
Die For Schleife wird ja schließlich bei jedem Programmstart ausgeführt.
Und somit wird Alles immer wieder neu reinkopiert.

Und genau das musst du jetzt ändern.
Also lagerst du die Forschleifen in Methoden aus.

  • Die Methode kopieren() kann dann die erste For-Schleife ausführen.
  • Und die Methode lesen() kann die Werte aus dem zweiten Array auslesen und auf der Konsole ausgeben.

Gesagt, getan.
So sieht es dann aus:

public class ArraysKopieren {

	static void kopieren(int[] original, int[] kopie) {
		for (int i = 0; i < kopie.length; i++) {
			kopie[i] = original[i];
		}
	}

	static void lesen(int[] kopie) {
		for (int i = 0; i < kopie.length; i++) {
			System.out.println(kopie[i]);
		}
	}

	public static void main(String[] args) {
		int arrayEins[] = new int[3];
		int arrayZwei[] = new int[3];

		arrayEins[0] = 2;
		arrayEins[1] = 9999;
		arrayEins[2] = 4;

		kopieren(arrayEins, arrayZwei);//Methodenaufruf mit Ursprungsdaten
	}
}

Ganz kurz:

  • Die Kopieren-Methode() erwartet in ihrer Parameterliste zwei Arrays.
    Das erste Array ist das aus dem gelesen wird. (Original)
    Das zweite Array ist das, in welches gespeichert wird. (Kopie)
  • Beim Methodenaufruf, in der main-Methode, übergebe ich das arrayEins als Original und das arrayZwei als Kopie.
  • In der Lesen Methode übergebe ich dann die Kopie.
    Und diese wird als Bildschirmausgabe zurückgegeben.

Jetzt verändere ich einmal den Wert des Originals.
Um es am Bücherbeispiel zu erklären: Ich male einen Strich auf die Originalseite.
Und schau mir die Kopie danach an.
Hier der Code:

public class ArraysKopieren {

	static void kopieren(int[] original, int[] kopie) {
		for (int i = 0; i < kopie.length; i++) {
			kopie[i] = original[i];
		}
	}

	static void lesen(int[] kopie) {
		for (int i = 0; i < kopie.length; i++) {
			System.out.println(kopie[i]);
		}
	}

	public static void main(String[] args) {
		int arrayEins[] = new int[3];
		int arrayZwei[] = new int[3];

		arrayEins[0] = 2;
		arrayEins[1] = 9999;
		arrayEins[2] = 4;

		kopieren(arrayEins, arrayZwei);//Methodenaufruf mit Ursprungsdaten
												
		liesArrayZwei(arrayZwei);// Zur Überprüfung
		System.out.println();// Zwischenzeile zur besseren Übersicht
		arrayEins[2] = 124;// Veränderung des Originals
		lesen(arrayZwei);// Zur Überprüfung
	}
}

Und wie sieht es aus?
Beim zweiten Aufruf der Lesen-Methoden() bleiben die Werte unverändert.

Das bedeutet:

  • Die Kopie ändert sich nicht, wenn sich das Original ändert.
  • Die Kopie würde sich erst ändern, wenn du nochmals die kopieren-Methode aufrufen würdest.

Denn anders als beim Umswitchen, arbeitest du hier mit zwei unterschiedlichen Arrays.
Durch die For-Schleife wird der Wert aus dem ersten Array herausgeholt und in das zweite Array gesteckt.

Ich höre dich sagen:

So ein Scheiß-
Hätte ich das Umswitchen in eine separate Methode ausgelagert -könnte ich die Arrays auch kopieren.

Komm schon – das wolltest du doch sagen, oder?
Okay, dann lass es uns testen.

Auf einen zweiten Versuch:
Lassen sich Java Arrays durch Umswitchen kopieren?

So würde der Code dazu aussehen:

public class ArraysKopieren {

	static void kopieren(int[] original, int[] kopie) {
		kopie = original; // Switch der Referenzvariablen
	}

	static void lesen(int[] kopie) {
		for (int i = 0; i < kopie.length; i++) {
			System.out.println(kopie[i]);
		}
	}

	public static void main(String[] args) {
		int arrayEins[] = new int[3];
		int arrayZwei[] = new int[3];
		arrayEins[0] = 2;
		arrayEins[1] = 9999;
		arrayEins[2] = 4;

		kopieren(arrayEins, arrayZwei);//Methodenaufruf
		lesen(arrayZwei);// Zur Überprüfung
		System.out.println();// Zwischenzeile zur besseren Übersicht
		arrayEins[2] = 124;// Veränderung des Originals
		lesen(arrayZwei);// Zur Überprüfung
	}
}

Ich habe lediglich die Kopieren-Methode verändert.
Im Methodenrumpf findet jetzt der Switch statt.

Also dann los.
Klick auf „RUN“ und siehe da…..
0,0,0,0,0,0 – Alles Nullen.

Offensichtlich funktioniert das NICHT!!!
Denn auch bei Referenzvariablen ist die Wertübergabe immer call-by-value.

  • Es wird somit lediglich eine Kopie der Speicheradresse an die Methode übergeben.
  • Diese Speicheradressen-Kopie ist auch nur eine lokale Variable für die Methode.
  • Und am Ende der Methode ist diese Kopie immer futsch.
    Sie wird zerstört.

Also lassen wir die Methode ein Array returnen und speichern diesen Return-Wert dann, in unserer Referenzvariable „arrayZwei“.
Vielleicht bringt uns das weiter.

Gesagt getan:


public class ArraysKopieren {

	//Methode ist nicht mehr void, sondern hat ein Integer-Array als Rückgabewert
	static int [] kopieren(int[] original, int[] kopie) {
		kopie = original; // Switch der Referenzvariablen
		return kopie;//Rückgabe des Kopie-Arrays
	}

	static void lesen(int[] kopie) {
		for (int i = 0; i < kopie.length; i++) {
			System.out.println(kopie[i]);
		}
	}

	public static void main(String[] args) {
		int arrayEins[] = new int[3];
		int arrayZwei[] = new int[3];
		arrayEins[0] = 2;
		arrayEins[1] = 9999;
		arrayEins[2] = 4;

		arrayZwei=kopieren(arrayEins, arrayZwei);// Zuweisung durch Methodenaufruf
		lesen(arrayZwei);
		System.out.println();
		arrayEins[2] = 124;
		lesen(arrayZwei);
	}
}

Wenn du jetzt noch einmal auf „RUN“ klickst, siehst du:

  • ArrayZwei erhält durch das Kopieren die Werte aus Array Eins.
  • Nachdem arrayEins aber nachträglich verändert wurde, veränderte sich automatisch auch ArrayZwei.
    Somit ist ArrayZwei wiederum keine Kopie von ArrayEins.

Und das wiederum bedeutet:

  • Durch das Switchen der Referenzvariablen ist kein Kopieren möglich.
  • Es wird nämlich dabei lediglich die Speicheradresse von einer Variable auf die andere übertragen.
  • Dadurch zeigen dann immer zwei Variablen auf ein-und-das-selbe Array.

Aber es gibt neben der For-Schleife noch zwei weitere Möglichkeiten Arrays zu kopieren.

So lassen sich Java Arrays klonen.

Die For-Schleife war so eine selbstgebaute Sache.
Die Java Bibliothek bringt aber schon ein nettes kleines Feature mit.

Denn jedes Array lässt sich automatisch klonen.
So wie hier:

public class ArraysKopieren {

	static void lesen(int[] kopie) {
		for (int i = 0; i < kopie.length; i++) {
			System.out.println(kopie[i]);
		}
	}

	public static void main(String[] args) {
		int arrayEins[] = new int[3];
		int arrayZwei[] = new int[3];
		arrayEins[0] = 2;
		arrayEins[1] = 9999;
		arrayEins[2] = 4;

		arrayZwei=arrayEins.clone();//Zuweisung über die clone-Methode
		lesen(arrayZwei);// Zur Überprüfung
		System.out.println();// Zwischenzeile zur besseren Übersicht
		arrayEins[2] = 124;// Veränderung des Originals
		lesen(arrayZwei);// Zur Überprüfung
	}
}

Die Kopieren-Methode fällt dann weg.
Und das was neu ist – habe ich einmal fett markiert.

Die Rückgabe der Clone()-Methode auf dem arrayEins, wird in der Referenzvariable arrayZwei gespeichert.
Fertig.

Wenn du jetzt wieder auf „RUN“ klickst, siehst du:

  • ArrayZwei erhält alle Werte vom arrayEins.
  • Wenn danach das Original „arrayEins“ geändert wird- hat das keinen Einfluss auf die Kopie „arrayZwei“.
    Somit wurde eine echte Kopie des ersten Arrays angelegt.

Also nutze zum Kopieren entweder eine selbstgebaute For-Schleife oder die clone-Methode.

Eine Möglichkeit stelle ich dir noch vor.
Und bekanntlich kommt das Beste immer zum Schluss.

Die flexibelste Möglichkeit ein Java Arrays zu kopieren, stellt die Klasse System bereit.

Auch hier der Code:

public class ArraysKopieren {

	static void lesen(int[] kopie) {
		for (int i = 0; i < kopie.length; i++) {
			System.out.println(kopie[i]);
		}
	}

	public static void main(String[] args) {
		int arrayEins[] = new int[3];
		int arrayZwei[] = new int[3];
		arrayEins[0] = 2;
		arrayEins[1] = 9999;
		arrayEins[2] = 4;

		System.arraycopy(arrayEins, 0, arrayZwei, 0, arrayZwei.length);
		lesen(arrayZwei);// Zur Überprüfung
		System.out.println();// Zwischenzeile zur besseren Übersicht
		arrayEins[2] = 124;// Veränderung des Originals
		lesen(arrayZwei);// Zur Überprüfung
	}
}

Was neu ist – ist wieder fett markiert.
Die System.arraycopy()-Methode verlangt schon ein paar Parameter:

  1. arrayEins- Ist das Originalarray aus dem die Daten stammen.
  2. 0 – Ist der Index von dem aus gelesen wird.
    Wenn du beispielsweise eine 1 angeben würdest- startet das Kopieren im zweiten Fach des Arrays „arrayEins“
  3. arrayZwei-Ist das Array in welches die Daten dann kopiert werden sollen.
  4. 0 – Ist der Index von dem aus gefüllt wird.
    Wenn du hier beispielsweise eine 1 angibst, dann würde die Methode das erste Fach freilassen.
    Und erst ab dem zweiten Fach das Array füllen.
  5. arrayZwei.length-Ist die Anzahl der Durchläufe.
    Ich habe hier die Länge des zweiten Arrays angegeben.
    Du kannst auch eine 3 -für drei Durchläufe-schreiben.

Wichtig ist auch hierbei.
Es handelt sich um eine echte Kopie. Nachdem diese angelegt wurde, kann das Original beliebig verändert werden.
Dies hat keinen Einfluss auf die Kopie.

Probiere die Methode ein bisschen aus.
Hier noch ein paar Beispiele.

public class ArraysKopieren {

	static void lesen(int[] kopie) {
		for (int i = 0; i < kopie.length; i++) {
			System.out.println(kopie[i]);
		}
	}

	public static void main(String[] args) {
		int arrayEins[] = new int[3];
		int arrayZwei[] = new int[3];
		arrayEins[0] = 2;
		arrayEins[1] = 9999;
		arrayEins[2] = 4;

		System.arraycopy(arrayEins, 1, arrayZwei, 0, arrayZwei.length-1);
		lesen(arrayZwei);
		System.out.println();
		arrayEins[2] = 124;
		lesen(arrayZwei);
	}
}

Jetzt beginnt das Kopieren erst im zweiten Fach des ersten Arrays.
Die kopierten Fächer des zweiten Arrays hätten demnach die Werte 9999, 4 und 0.
Das Fach arrayEins[0] = 2 wurde also übersprungen.

Ganz wichtig ist:
Die Anzahl der Durchläufe muss verändert werden.
Denn dadurch dass das Fach 0 übersprungen wurde, können jetzt keine drei Durchläufe mehr stattfinden.
Du musst die Anzahl somit kürzen: arrayZwei.length-1.

Denn wenn du dies nicht tust, bekommst du eine „IndexOutOfBound“-Exception.

Nächste Beispiel:

public class ArraysKopieren {

	static void lesen(int[] kopie) {
		for (int i = 0; i < kopie.length; i++) {
			System.out.println(kopie[i]);
		}
	}

	public static void main(String[] args) {
		int arrayEins[] = new int[3];
		int arrayZwei[] = new int[3];
		arrayEins[0] = 2;
		arrayEins[1] = 9999;
		arrayEins[2] = 4;

		System.arraycopy(arrayEins, 1, arrayZwei, 1, arrayZwei.length-1);
		lesen(arrayZwei);
		System.out.println();
		arrayEins[2] = 124;
		lesen(arrayZwei);
	}
}

Die Ausgabe wäre dann 0, 9999 und 4.
Jetzt wird beim Lesen das Fach Null übersprungen. Der Wert 2 fällt somit sowieso weg.
Beim Kopieren wird das Fach Null ebenfalls übersprungen und bekommt lediglich den Default-Wert 0.

Natürlich kannst du auch aus dem zweiten Array in das erste kopieren.

public class ArraysKopieren {

	static void lesen(int[] kopie) {
		for (int i = 0; i < kopie.length; i++) {
			System.out.println(kopie[i]);
		}
	}

	public static void main(String[] args) {
		int arrayEins[] = new int[3];
		int arrayZwei[] = new int[3];
		arrayEins[0] = 2;
		arrayEins[1] = 9999;
		arrayEins[2] = 4;

		System.arraycopy(arrayZwei, 1, arrayEins, 1, arrayZwei.length-1);
		lesen(arrayZwei);
		System.out.println();
		arrayEins[2] = 124;
		lesen(arrayZwei);
	}
}

Für unser Beispiel ergibt das aber wenig Sinn, da wir das zweite Array nie gefüllt haben.
Als Ausgabe erscheinen dann nur die Default-Werte 0, 0 und nochmals 0.

Zusammenfassung:

  • Durch Umswitchen von Referenzvariablen, legst du keine Kopie von Java Arrays an.
    Stattdessen zeigen dann nur zwei Referenzvariablen auf „ein-und-das-selbe“ Array.
  • Und das ist dann so, wie die Geschichte mit dem Buch, dem Kopierer und dem Stift.
    Du veränderst dann immer das Original.
  • Stattdessen kannst du Java Arrays kopieren, indem du mit for-Schleifen arbeitest oder die javainternen Methoden wählst.
  • Durch die Clone-Methode erschaffst du eine 1:1 Kopie des Arrays.
  • Durch die System.arraycopy()-Methode kannst du flexibel wählen, welche Fächer du kopieren möchtest.
    Und welche Fächer du überspringen möchtest.

Über den Autor

wissen
Folge Sciodoo und bleibe stets auf dem Laufenden. Schließ dich uns an und abonniere unseren Instagram-Kanal ein. Wir stellen täglich neue Artikel für dich rein.
Weiter zum Kanal>>>
     

Ähnliche Beiträge