Call by Value: Unterschied zwischen den Versionen

Aus EINI
Wechseln zu: Navigation, Suche
K
Zeile 6: Zeile 6:
  
 
Immer wenn eine Methode aufgerufen wird, werden übergebene Variablen zuerst aufgelöst und dann der resultierende Wert übergeben. Nehmen wir als Beispiel folgende zwei [[static | statische]] Methoden:
 
Immer wenn eine Methode aufgerufen wird, werden übergebene Variablen zuerst aufgelöst und dann der resultierende Wert übergeben. Nehmen wir als Beispiel folgende zwei [[static | statische]] Methoden:
 +
 
<source lang="java">
 
<source lang="java">
 
public static void caller(){
 
public static void caller(){
 
     int i = 5;
 
     int i = 5;
 
     callee(i);
 
     callee(i);
 +
    System.out.println(i);
 
}
 
}
 
public static void callee(int a){
 
public static void callee(int a){
Zeile 16: Zeile 18:
 
</source>
 
</source>
  
Die Methode <code>caller()</code> deklariert eine <code>int</code> Variable <code>i</code> mit dem Wert 5. Beim Aufruf von <code>callee(int a)</code> wird die übergebene Variable <code>i</code> nun zuerst zum Wert 5 aufgelöst. Dann wird die Funktion <code>callee(int a)</code> mit dem Wert 5 aufgerufen. Der Aufruf <code>callee(i)</code> ist also in diesem Falle nicht zu unterscheiden von einem Aufruf <code>callee(5)</code>. Hier sieht man zudem den Grund für das Verhalten von '''Call by Value''':
+
Der unerfahrene Programmierer, der diesen Code schreiben mag, wird hier denken, die Ausgabe des Programmes sei '''10'''. Tatsächlich ist sie jedoch '''5'''.
  
Eine Funktion, die primitive Daten als Parameter erwartet, kann mit konstanten Werten wie <code>callee(5)</code> aufgerufen werden. Der Aufruf kann in diesem Fall keinen Einfluss auf die 5 haben, da der Ausdruck '''5''' konstant ist.
+
Die Methode <code>caller()</code> deklariert eine <code>int</code> Variable <code>i</code> mit dem Wert 5. Beim Aufruf von <code>callee(int a)</code> wird die übergebene Variable <code>i</code> nun zuerst zum Wert 5 aufgelöst. Dann wird die Funktion <code>callee(int a)</code> mit dem Wert 5 aufgerufen. Der Aufruf <code>callee(i)</code> ist also in diesem Falle nicht zu unterscheiden von einem Aufruf <code>callee(5)</code>.
  
Was tatsächlich passiert, ist, dass beim Aufruf einer Funktion ein neuer [[Stack#Stackframe | Stackframe]] für diesen Aufruf auf den [[Stack]] gelegt wird und die lokalen Parametervariablen innerhalb dieses Stackframes mit den übergebenen Werten initialisiert werden. Ein '''konstanter''' Aufruf von <code>callee(int a)</code> mit der Zahl 5 wäre also praktisch nicht zu unterscheiden von einer Methode, die folgendermaßen aussieht:
+
Eine Funktion, die primitive Daten als Parameter erwartet, kann mit konstanten Werten wie <code>callee(5)</code> aufgerufen werden. Deshalb kann in diesem Falle ein Aufruf mit 5 keinen Einfluss auf die 5 haben, da der Ausdruck "5" konstant ist.
  
<source lang="java">
+
Was tatsächlich passiert, ist, dass beim Aufruf einer Funktion ein neuer [[Stack#Stackframe | Stackframe]] für diesen Aufruf auf den [[Stack]] gelegt wird und die lokalen Parametervariablen innerhalb dieses Stackframes mit den übergebenen Werten initialisiert werden.
public static callee(){
+
    int a = 5;
+
    a = a + 5;
+
}</source>
+
  
Da man jedoch eine Funktion für verschiedene Zwecke wieder verwenden will, versieht man Funktionen mit von außen veränderbaren Parametern, um eine allgemeine Lösung für verschiedene Probleme bereit stellen zu können.
+
Möchte man im Beispiel oben, den Wert der Variablen '''i''' außerhalb der Funktion ändern, so wird man enttäuscht. Dies ist in Java mit primitiven Daten nicht möglich. Man benötigt eine Funktion mit einer [[Rückgabe]], das heißt die Funktion muss eine Eingabe erhalten, etwas berechnen und das Ergebnis der Berechnung ''explizit'' zurück geben. Der zurückgegebene Wert muss dan der Variablen als neuer Wert zugweiesen werden:
 
+
Möchte man im Beispiel oben, den Wert der Variablen '''a''' außerhalb der Funktion ändern, benötigt die Funktion eine [[Rückgabe]], das heißt die Funktion muss eine Eingabe erhalten, etwas berechnen und das Ergebnis der Berechnung ''explizit'' zurück geben.
+
  
 
<source lang="java">
 
<source lang="java">
 
public static void caller(){
 
public static void caller(){
     int a = 5;
+
     int i = 5;
     a = callee(5);
+
     i = callee(5);
 
}
 
}
  

Version vom 7. Februar 2016, 19:00 Uhr

Als Call by Value bezeichnet man den Mechanismus der Parameterübergabe von primitiven Datentypen. Sein Pendant ist der Mechanismus des Call by Reference.

Dabei wird beim Aufruf einer Funktion der Wert einer Variable zuerst aufgelöst und dann direkt an die aufrufende Methode übergeben. Es wird also eine Kopie des Wertes der Variablen übergeben. Da die Parameter einer Funktion lokal auf dem Stack der Methode liegen, sind diese unabhängig von denen, die beim Aufruf der Methode verwendet wurden. Änderungen an den Parametervariablen innerhalb einer aufgerufenen Methode haben demnach keinen Einfluss auf die Werte der übergebenen Variablen innerhalb der aufrufenden Methode.

Verwendung

Immer wenn eine Methode aufgerufen wird, werden übergebene Variablen zuerst aufgelöst und dann der resultierende Wert übergeben. Nehmen wir als Beispiel folgende zwei statische Methoden:

public static void caller(){
    int i = 5;
    callee(i);
    System.out.println(i);
}
public static void callee(int a){
    a = a + 5;
}

Der unerfahrene Programmierer, der diesen Code schreiben mag, wird hier denken, die Ausgabe des Programmes sei 10. Tatsächlich ist sie jedoch 5.

Die Methode caller() deklariert eine int Variable i mit dem Wert 5. Beim Aufruf von callee(int a) wird die übergebene Variable i nun zuerst zum Wert 5 aufgelöst. Dann wird die Funktion callee(int a) mit dem Wert 5 aufgerufen. Der Aufruf callee(i) ist also in diesem Falle nicht zu unterscheiden von einem Aufruf callee(5).

Eine Funktion, die primitive Daten als Parameter erwartet, kann mit konstanten Werten wie callee(5) aufgerufen werden. Deshalb kann in diesem Falle ein Aufruf mit 5 keinen Einfluss auf die 5 haben, da der Ausdruck "5" konstant ist.

Was tatsächlich passiert, ist, dass beim Aufruf einer Funktion ein neuer Stackframe für diesen Aufruf auf den Stack gelegt wird und die lokalen Parametervariablen innerhalb dieses Stackframes mit den übergebenen Werten initialisiert werden.

Möchte man im Beispiel oben, den Wert der Variablen i außerhalb der Funktion ändern, so wird man enttäuscht. Dies ist in Java mit primitiven Daten nicht möglich. Man benötigt eine Funktion mit einer Rückgabe, das heißt die Funktion muss eine Eingabe erhalten, etwas berechnen und das Ergebnis der Berechnung explizit zurück geben. Der zurückgegebene Wert muss dan der Variablen als neuer Wert zugweiesen werden:

public static void caller(){
    int i = 5;
    i = callee(5);
}

public static void callee(int a){
    return a + 5;
}