Java: Call-by-Value oder Call-by-Reference?

von Hubert Schmid vom 2013-01-13

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.