Java: Call-by-Value oder Call-by-Reference?
Verwendet Java Call-by-Value
oder Call-by-Reference
? Zu dieser Frage gibt es immer wieder Diskussionen. Dabei ist die Sache doch ganz einfach.
Java unterscheidet zwischen primitiven Datentypen und Objekten. Für primitive Datentypen ist die Antwort auf die Frage klar: Der Aufruf erfolgt mit Call-by-Value
. Das ist auch im folgenden Listing zu sehen, das eine Methode mit einem int
-Parameter enthält. Innerhalb der Methode erfolgt eine Zuweisung an den Parameter. Das ist erlaubt, hat jedoch keine Auswirkung auf das Argument, das der Aufrufer übergeben hat. Das ist ein klares Zeichen für Call-by-Value
.
void foobar(int value) {
value += 42;
}
Betrachten wir also nun ein Beispiel mit Objekten statt primitiven Datentypen. Im folgenden Listing ist zu sehen, wie die Methode append
mit einem StringBuilder
aufgerufen wird, der innerhalb der Methode verändert wird. Das ausgeführte Programm gibt 42
aus, was demonstriert, dass das Objekt tatsächlich verändert wird. Also verwendet Java Call-by-Reference
für Objekte, oder?
public class Answer {
public static void main(String... args) {
StringBuilder sb = new StringBuilder("4");
append(sb);
System.out.println(sb);
}
private static void append(StringBuilder sb) {
sb.append("2");
}
}
Die Frage lässt sich anhand des Beispiels nicht klar beantworten. In dem Beispiel ist lediglich zu sehen, wie sich das übergebene Objekt ändert. Das ist allerdings nicht das Gleiche wie Call-by-Reference
. Die entscheidende Frage ist: Kann man den Parameter ändern, so dass die Änderung beim Aufrufer sichtbar wird?
Also betrachte ich ein weiteres Beispiel, und dieses Mal wird der Parameter direkt geändert. Die Ausführung zeigt, dass die Änderung keine Wirkung hat. Statt 42
wird 54
ausgegeben. Also verwendet Java Call-by-Value
für Objekte, oder?
public class Answer {
public static void main(String... args) {
StringBuilder sb = new StringBuilder("54");
answer(sb);
System.out.println(sb);
}
private static void answer(StringBuilder sb) {
sb = new StringBuilder("42");
}
}
Richtig! Java verwendet Call-by-Value
sowohl für primitive Datentypen als auch für Objekte. Letzteres wird manchmal zur Präzisierung auch Call-by-Value where the value is a reference
genannt – doch es ist immer noch ein Call-by-Value
.