call by reference & value

hos15

Aktives Mitglied
Hallo Liebe Java Freunde,
ich verstehe leider nicht den unterschied zwischen diesen beiden Begriffen. Ich habe mich im Internet umgeschaut und finde keine Erklärung wo es wirklich "Klick " macht und ich das selber
an ein Beispiel sagen ob eine Methode als call by reference oder value geschrieben ist.

Ansicht kann ich diese Beiden worte " gut " erklären z.B :
Florian hat ein Bild und möchte das an Sabine schicken. Wenn Florian das Bild Kopiert und an
Sabine schickt dann hat Sabine das gleiche Bild. Führt Sabine Veränderung an diesem Bild dann hat es keine Auswirkung auf Florians Bild. (Call by Value). Wenn Florian jedoch ein link an Sabine sendet wo das Bild zu sehen ist dann sind jegliche Veränderungen die Sabine führt auch bei Florian zu sehen. (Call by reference)
oder anders:
Einfache Werte werden kopiert und Änderungen
an den lokalen Kopien haben keine weiteren Auswirkungen Call by Value). Bei komplexen
Werten wird eine Referenz übergeben, mittels derer die Methode auf die
Inhalt zugreifen und sie dauerhaft verändern kann.(Call by reference)

Aber leider kann ich das nicht auf Methoden umsetzen wenn mir 2 Methoden angezeigt werden kann ich nicht sagen ob das Cbv oder Cbr ist.
z.B diese Methoden

Java:
static int[] legeQuadrateAn( int l ) {
int[] feld = new int[l];
for( int i=0; i<l; i++ ) feld[i] = i*i;
return feld;
}

Java:
static void tausche( int[] feld, int i, int j ) {
int tmp = feld[i];
feld[i] = feld[j];

feld[j] = tmp;
}
 
Erstmal, java macht immer call-by-value, es kann auch gar nichts anderes.
Java unterscheidet zwischen primitiven Typen (int, char, etc) und Referenztypen (Objekte). Die primitiven Typen beinhalten direkt ihren entsprechenden Wert. Referenztypen beinhalten eine Referenz, welche auf das konkrete Objekt im heap zeigt.
Wenn du nun einen primitiven Typen an eine Methode übergibst, so wird einfach der Wert kopiert.
Java:
void test(int i) { i = 5; }
// ...
int x = 42;
test(x);
System.out.println(x); // immernoch 42
Das gleiche gilt auch für Objekte, aber wie bereits oben erwähnt, ist eine Variable auf ein Objekt erstmal nur eine Referenz, d.h. es wird auch nur die Referenz kopiert:
Java:
void test(Point p) { p = new Point(1,1); }
// ...
Point point = new Point(42, 20);
test(point);
System.out.println(point.x); // immernoch 42
Eine neue zuweisung hat also keinerlei Auswirkung auf die "ursprüngliche" Variable, da es eben zwei Referenzen sind, welche halt nur auf das gleiche Objekt zeigten.

Allerdings kann man natürlich von beiden Referenzen aus das Objekt verändern:
Java:
void test(Point p) { p.x = 10; }
// ...
Point point = new Point(42, 20);
test(point);
System.out.println(point.x); // 10
Die Referenzen zeigen auf das gleiche Objekt und können es somit beide verändern.
 
call by reference:
Wenn du ein Objekt nach dem erstellen einem anderen Objekt übergibst und es dann dort verändert wird, dann ist das Objekt überall verändert wo es momentan existiert.

Bsp.:
Code:
  String[] myArray = {"a", "b"};
  new VereandereArray(myArray); // call by reference
  System.out.println(myArray);  // {"a", "b", "neuer Inhalt"}

call by value:
Hier würde das Array "myArray" nicht verändert. In Java ist das aber nur mit primitiven Daten möglich. Hier also nicht möglich! Wenn man nicht das Originale Objekt verändern möchte, erstellt man eine Kopie davon und übergibt die Kopie.

Bsp.:
Code:
  int myInt = 5;
  new VereandereMich(myInt); // call by value
  System.out.println(myInt); // bleibt 5 !!
 
Zuletzt bearbeitet:
nein, das ist nicht call-by-reference. In Java werden Parameter immer by value übergeben.
Dies siehst du eben an diesem einfachen Beispiel:
Java:
void f(int[] arr) {
  arr = {1,2,3};
}
// ...
int[] werte = {42};
f(werte);
System.out.println(Arrays.toString(werte));
Wenn Java wirklich by-reference arbeiten könnte, so würde nun das Array {1,2,3} ausgegeben werden, da die Referenz verändert werden konnte.
Beim Ausführen wird man aber feststellen, das weiterhin {42} ausgegeben, obwohl dem Parameter ein neuer Wert zugewiesen wurde. Dies liegt eben genau daran, dass Java die Parameter immer via call-by-value übergibt.

Parameter werden bei Java immer kopiert. Bei Objekten führt das dazu dass die Referenz auf das Objekt im Heap kopiert wird. Somit besitzen Caller und Callee jeweils eine eigene, unabhängige Referenz, welche bloß auf das gleiche Objekt im Heap zeigen. Klar, mit beiden Referenzen kann man dieses Objekt nun manipulieren, aber das ändern der Referenz selber, hat keine Auswirkungen auf die andere Referenz.
 
Java:
class ChangeArray
{
  public void add(String[] myArray) {
    myArray[1] = "new";
  }
}


public class Test
{
  public static void main(String[] args) {
    String[] myArray = new String[2];
    myArray[0] = "a";

    for (String tmp : myArray) {
      System.out.println(tmp);
    }

    ChangeArray changer = new ChangeArray();
    changer.add(myArray);

    System.out.println("---------------------------");
    for (String tmp : myArray) {
      System.out.println(tmp);
    }

//    output:
//    a
//    null
//    ---------------------------
//    a
//    new
  }
}
 
Dort wird das Objekt verändert, auf welches die Referenz zeigt, nicht aber die Referenz selber, denn diese ist nur eine Kopie der original Referenz. Objekte liegen bei Java immer im Heap und werden nur durch Referenzen angesprochen.
http://openbook.rheinwerk-verlag.de/javainsel9/javainsel_03_005.htm
http://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value
http://javadude.com/articles/passbyvalue.htm
etc. ...

edit:
original von Oracle:
Reference data type parameters, such as objects, are also passed into methods by value. This means that when the method returns, the passed-in reference still references the same object as before. However, the values of the object's fields can be changed in the method, if they have the proper access level.
 
Zuletzt bearbeitet:
Das ist richtig, habe ich auch nie geleugnet^^
Aber bei der Parameterübergabe, geht es eben um die Variable selber, welche entweder ein primitiver Typ ist oder eine Referenz. Das Objekt (also dessen Felder) auf welches gezeigt wird kann dabei verändert werden
 
In Java ists leicht:
primitive Datentype->CallByValue, Objekte->CallByRef

int wäre als CbV, int[] CbR

Gut, dass jemand noch mal gepostet hat, dass es in Java ausschließlich CbV lt. Definition gibt. Und das von dir, wo du alles besser wissen möchtest, hätte ich nicht erwartet. Desweiteren sind eure Erklärungen alle etwas schwach, nicht so, wie aus dem Lehrbuch...
 
Zuletzt bearbeitet von einem Moderator:
Hier mal die offiziellen Erklärungen: JLS 8.4.1
When the method or constructor is invoked (§15.12), the values of the actual argument expressions initialize newly created parameter variables, each of the declared type, before execution of the body of the method or constructor. The Identifier that appears in the DeclaratorId may be used as a simple name in the body of the method or constructor to refer to the formal parameter.
Dann auch noch aus den Tutorial-Seiten.
 

Zurück
Oben