Call By Value nennt man die in Java realisierte Form des Methodenaufrufs, bei dem Kopien von Werten und nicht die Werte selbst als Parameter übergeben werden.
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.
Wenn Ihnen javabeginners.de gefällt, freue ich mich über eine Spende an diese gemeinnützigen Organisationen.