Eine Variable stellt bekanntlich eine Referenz auf eine
Speicherstelle dar. Soll der Wert der Speicherstelle in einer Methode
bearbeitet werden, so wird beim Methodenaufruf der Inhalt der
Speicherstelle, also der Wert kopiert und diese Kopie als Parameter an die
Methode übergeben. Das bedeutet, dass der Originalwert unbeeinflusst bleibt.
Das folgende Beispiel zeigt dies dadurch, dass die Ausgaben vor und nach dem
Methodenaufruf identisch sind. Innerhalb der Methode werden lediglich die
Werte der Parameter getauscht und der eventuell beabsichtigte Tausch der
Variablen ist fehlgeschlagen.
public class CallByValue {
public static void main(String[] args) {
int a = 0;
int b = 100;
System.out.println("a: " + a + ", b: " + b);
pseudoSwapInt(a, b);
System.out.println("a: " + a + ", b: " + b);
}
private static void pseudoSwapInt(int pA, int pB) {
int temp = pA;
pA = pB;
pB = temp;
System.out.println("pA: " + pA + ", pB: " + pB);
}
}
Selbstverständlich gilt dies nicht nur für primitive Datentypen, sondern
auch für Referenztypen. Wie aber verhält es sich in einem solchen Fall mit
deren Eigenschaften? Natürlich genauso, da die Parameter Kopien der
Referenz, also des Verweises auf die Speicheradresse, darstellen.
Original-Variable und Parameter zeigen also auf die selben (nicht nur
gleichen) Werte. Innerhalb der Methode pseudoSwap() werden im
Beispiel also nur die Zeiger auf die Speicherstellen beider Point-Objekte
getauscht. Die Objekte selbst bleiben mit ihren Eigenschaften an den selben
Speicherstellen unverändert erhalten.
import java.awt.Point;
public class Call_by_Value2 {
public static void main(String[] args) {
Point p1 = new Point(0, 0);
Point p2 = new Point(100, 100);
System.out.println("p1: " + p1.x + "|" + p1.y); // p1: 0|0
System.out.println("p2: " + p2.x + "|" + p2.y); // p2: 100|100
pseudoSwap(p1, p2);
System.out.println("nach Methodendurchlauf:");
System.out.println("p1: " + p1.x + "|" + p1.y); // p1: 0|0
System.out.println("p2: " + p2.x + "|" + p2.y); // p2: 100|100
}
private static void pseudoSwap(Point pp1, Point pp2){
Point temp = pp1;
pp1 = pp2;
pp2 = temp;
System.out.println("innerhalb pseudoSwap():");
System.out.println("p1: " + pp1.x + "|" + pp1.y); // p1: 100|100
System.out.println("p2: " + pp2.x + "|" + pp2.y); // p2: 0|0
}
}
Nun sollte auch der dritte Fall einleuchten. In ihm werden
Membervariablen eines übergebenen Referenztyps dauerhaft geändert.
import java.awt.Point;
public class Call_by_Value3 {
public static void main(String[] args) {
Point p1 = new Point(0, 0);
Point p2 = new Point(100, 100);
System.out.println("p1: " + p1.x + "|" + p1.y); // p1: 0|0
System.out.println("p2: " + p2.x + "|" + p2.y); // p2: 100|100
changePointValue(p1, p2);
System.out.println("nach Methodendurchlauf:");
System.out.println("p1: " + p1.x + "|" + p1.y); // p1: 50|50
System.out.println("p2: " + p2.x + "|" + p2.y); // p2: 100|100
}
private static void changePointValue(Point pp1, Point pp2){
System.out.println("Innerhalb changePointValue()");
pp1.x = 50;
pp1.y = 50;
System.out.println("nach Wertezuweisung:");
System.out.println("pp1: " + pp1.x + "|" + pp1.y); // p1: 50|50
System.out.println("pp2: " + pp2.x + "|" + pp2.y); // p2: 100|100
Point temp = pp1;
pp1 = pp2;
pp2 = temp;
System.out.println("nach Referenztausch:");
System.out.println("pp1: " + pp1.x + "|" + pp1.y); // p1: 100|100
System.out.println("pp2: " + pp2.x + "|" + pp2.y); // p2: 50|50
}
}
Das Ergebnis verwirrt zunächst, klärt sich jedoch bei genauerer Betrachtung,
wenn man beachtet, dass innerhalb von changePointValue() zunächst
die Werte geändert werden, auf die die als Parameter übergebene Referenz
zeigt. Dies ist ja eine Kopie der Ausgangsreferenz, die ja auf das
eigentliche Objekt zeigt. Es besitzt somit jetzt zwei Zeiger, die das selbe
Objekt betreffen. Ändert man jetzt dessen Eigenschaften, ist dies natürlich
dauerhaft.
Nach dem Tausch der Objektreferenzen zeigen sich dann
selbstverständlich auch deren Eigenschaften als ausgetauscht (weil ja die
Verweise getauscht wurden). Das ist jedoch über den Lebenszyklus der Methode
hinaus nicht dauerhaft, weil innerhalb der Methode wiederum nur mit
Kopien der Referenzen gearbeitet wurde.