# Stack/Heap Frage



## b1zarRe (17. Jul 2012)

Hi,

kleine Frage zur Identität/Referenz:

Hier der Code:


```
String f="a";
        String g="a";
        System.out.println(f==g); //true!
        g="nicht a";
        System.out.println(f);
```

Müsste nicht, die Ausgabe "nicht a" ausgeben???
Ich meine ich erzeuge zwei String Variablen f und g. Und da String ein Referenztyp/Klasse ist (und kein elementarer Wert) müsste Java doch auf dem Stack für f ung g den gleichen Zeiger in dem Heap haben mit dem Wert "a". Nun setze ich den Wert auf den g zeigt(welcher ja auch der von f sein sollte) auf:
"nicht a". Und gebe am Ende f aus... Meine Vermutung war, dass nun auch "nicht a" herauskommen muss.. aber es kommt "a" heraus. Woran liegt das!?!?


----------



## Gast2 (17. Jul 2012)

Ist doch eigentlich klar?!

Du weißt der Variablen g einen neuen Wert zu. Natürlich zeigt f noch auf seinen alten Wert, warum sollte sich das ändern?


----------



## kaschik (17. Jul 2012)

f referenziert das Objekt "a" aus dem String-Pool und selbiges macht g. Sie referenzieren das selbe Objekt, denn es gibt im String-Pool nur ein "a". Deswegen ist f == g auch true. Trotzdem sind f und g eigenständige Referenzen, was zur Folge hat, dass eine Änderung von f nicht auch g verändert.


----------



## b1zarRe (18. Jul 2012)

Ist die Erklärung nicht viel mehr, dass ich mit

```
g="nicht a";
```
ein neues StringObjekt erzeugt habe??? Und somit g darauf zeigt und f immernoch auf das alte???
- Das wäre momentan der einzige Weg der mir schlüssig erscheint. - Andererseits finde ich es
halt noch nicht 100% schlüssig, weil dann wäre der Code gleichzusetzen mit:

```
g=new String("nicht a");
```


Weil: 

```
public class CallByReference2 {

    public static void gibArrayAus(int[] a) {
        for(int i=0; i<a.length;i++) {
            System.out.print(a[i] + ",");
        }
        System.out.println("");
    }
    
    public static void callByReference(int[] neuesArray, int zahl) {
        neuesArray[0] = zahl;
    }
    
    public static void main(String[] args) {
        
        // Stack: array -> <adr1> Heap: <adr1: {1,2,3}>
        System.out.println("Vorher: ");
        int[] array = {1,2,3};
        gibArrayAus(array);
        System.out.println("");
        
        // Stack: neu=10; array-><adr1> Heap: <adr1: {1,2,3}>
        int neu = 10;
        
        // Methodenausführung
        callByReference(array, neu);
        
        // Nachher
        System.out.println("Nachher: ");
        gibArrayAus(array);
        System.out.println(""); 
    }
```

Verändert sehr wohl den Inhalt des Arrays "array". Ich dachte daher, dass es bei Strings genauso sein muss, da meines Wissens es in Java zu einem CallByReference kommen kann, wenn man mit nicht elementaren Datentypen arbeitet.(und String ist ja sogesehen nicht elementar wie zb. int, double etc.)


----------



## Gast2 (18. Jul 2012)

In Java gibt es nur call-by-value. Ausschließlich. Nichts anderes.
(Erklärung siehe hier: http://www.java-forum.org/allgemeines/4904-call-value-call-reference.html)



> Ist die Erklärung nicht viel mehr, dass ich mit [...] ein neues StringObjekt erzeugt habe???


Nein, du hättest auch ein bestehendes Objekt zuweisen können. Der Punkt ist, dass du der Variablen einen neuen "Wert" zuweist.

Was dein Code mit dem oben geschilderten Problem zu tun haben soll verstehe ich nicht ganz.


----------



## hüteüberhüte (18. Jul 2012)

```
String s
```
 ist eine Variable, die als Wert eine Referenz speichert. Bei einer Zuweisung wird der Wert, also die Referenz, geändert. Wenn der Variablen eine Referenz auf ein String-Objekt aus dem String-Pool zugewiesen wird, kann es natürlich sein, dass zwei Variablen als Wert die gleiche Referenz haben. Wenn dann allerdings eine neue Zuweisung erfolgt, ändert sich nur die Referenz der einen Variablen. Das beeinflusst nicht die Referenz der anderen Variablen

Sobald du irgendeine Methode mit einem Array aufrufst, liegt ein Objekt vor, dessen Werte/Elemente/Attribute/Variablen, bzw. dessen Zustand, geändert werden kann. Strings sind aber unveränderlich. Trotzdem würde eine Zuweisung an die Array-Variable nichts am ursprünglichen Array ändern


----------



## b1zarRe (18. Jul 2012)

Stimmt, Strings sind unveränderlich... denke das ist es es!!!

Zum anderen Code: Guckt euch den doch mal genauer an.. Ich erzeuge in der Main eine Array mit drei Zahlen. Übergebe
dieses Array einer Methode welches in einem NEUENarray eine zahl darin abändert soll. Gebt nun aber mal das ALTE array aus.... siehe da... es hat sich auch verändert!!


----------



## Gastredner (18. Jul 2012)

Das liegt darin begründet, dass Arrays bei der Übergabe als Parameter wie Objekte behandelt werden. Es wird also die Referenz auf das Array kopiert und nciht das Array selbst, weshalb Änderungen an diesem auch anderswo sichtbar werden.


----------



## new! (18. Jul 2012)

Liest du dir die bereits gegebenen Antworten überhaupt durch? In Java gibt es kein "Call by Reference"!



> Übergebe dieses Array einer Methode welches in einem NEUENarray eine zahl darin abändert soll.


Neue Arrays erzeugt man mit new. Kommt das auch nur irgendwo in deinem Code vor?


----------



## Gast2 (18. Jul 2012)

@b1zarRe
Ich glaube du hast das noch nicht ganz durchschau. Dass Strings immutable sind hat mit dem verhalten rein gar nichts zu tun. Das funktioniert genau mit jedem anderen Typ.

Dein Beispiel oben hat mit zuletzt geposteten auch rein gar nichts zu tun. Das zweite zeigt nur dass man schnell mal call-by-reference und call-by-value durcheinander bringen kann (was du da scheinbar gemacht hast).


----------



## b1zarRe (18. Jul 2012)

Ich meint damit, dass es zu einen CallByReference EFFEKT kommen kann(siehe Code oben);
Und auch hier ein Verweis: Einführung in die Programmierung - Korrektheit, Zusicherungen, Hoare-Kalkül | Video online

Und deshalb stellte sich mir die Frage, warum es nicht bei Strings genauso funktioniert, da Strings ja kein elementarer
Typ sind... aber denke das liegt damit zusammen, da Strings immutable sind...?

Und ja, ich lese mir die Antworten hier durch... Aber es bringt nichts zu sagen "Gibt es nicht" oder Ähnliches.
Ich will ja verstehen, warum es bei Arrays so klappt und bei Strings anders.


----------



## new! (18. Jul 2012)

Jetzt verstehe ich langsam, worauf du überhaupt hinaus willst.
Und ja, du hast recht, das liegt daran, dass Strings immutable sind. Wenn du statt Strings ein mutable Objekt wie StringBuilder verwendest, kommt es auch zu diesem "call-by-reference-Effekt".


```
public static void callByReference(StringBuilder sb, char replacement) {
        sb.setCharAt(1, replacement);
    }
    
    public static void main(String[] args) {
        StringBuilder string = new StringBuilder("Hase");
        System.out.println(string); // Hase
        callByReference(string, 'o');
        System.out.println(string); // Hose
    }
```


----------



## hüteüberhüte (18. Jul 2012)

Wenn ihr in diesem Zusammenhang von call-by-reference unterhaltet, kommt es schnell zu Missverständnissen. Die Parameterübergabe ist immer call-by-value. Der Wert einer Referenzvariablen ist eben eine Referenz, die dann kopiert wird. Der Wert eines primitive data types ist eben der Wert an sich, der in diesem Fall kopiert wird

Bei einem Methodenaufruf wird immer der Wert des actual parameters kopiert und an den formal parameter zugewiesen

Hier ist eine Auflistung der Primitiven: Primitive Data Types (The Java™ Tutorials > Learning the Java Language > Language Basics) (Ist nur sehr lang)


----------



## new! (18. Jul 2012)

Dann schreib doch eine E-Mail an Dr. Peer Kröger von der LMU und frag ihn, wieso er in seinen Vorlesungen so eine S*****e verzapft. xD


----------



## hüteüberhüte (18. Jul 2012)

[OT]Gib ihm doch einen Hinweis xD Aber das hat doch jetzt keine Relevanz für dieses Thema. Edit: Also hat der Link auch nichts mit dem Thema zu tun[/OT]


----------



## b1zarRe (18. Jul 2012)

@new!
Ja genau... Ich finde das Beispiel garnicht so dumm und die Erklärung(ein Video vorher) auch sehr sinnig.
Tipp doch das Beispiel mal ein, anstatt direkt zu behaupten das es quatsch ist... Man sollte kritisch sein/bleiben
und nicht direkt alles niederschmettern.

@hüteüberhüte
was du in dem letzten Post geschrieben hast.... !? Verstehe ich nicht..


----------



## hüteüberhüte (18. Jul 2012)

Was verstehst du denn nicht? Actual/formal parameter?: What is the difference between actual and formal parameters Call-by-value?: http://www.java-forum.org/allgemeines/4904-call-value-call-reference.html oder Hunderte andere Seiten


----------



## Mujahiddin (18. Jul 2012)

Ich weiß auch nicht, was es da nicht zu verstehen gibt.
Der Code 
	
	
	
	





```
Object o = new Object(){public String toString(){ return "Hallo!";} };
```
 erzeugt ein Objekt und o ZEIGT auf dieses Objekt. Wenn du jetzt eine Methode hast:

```
public void boo(Object someObject){
    someObject = new Object(){
        public String toString(){
            return "Tschüss!";
        }
    };
}
```
 und o diesem Objekt übergibst, ändert sich o nicht! o bleibt IMMER gleich, außer du veränderst o *direkt*. o würde in diesem Fall also weiterhin "Hallo!" ausgeben.

Das gleiche gilt für Strings.

```
String s = "Hallo!";
String t = "Hallo!";
t = "Tschüss!";
```
Wieso sollte sich da 
	
	
	
	





```
s
```
 ändern? Du fässt s doch gar nicht an!


----------



## b1zarRe (18. Jul 2012)

Warum ändert sich dann hier der Inhalt von von a *indirekt*:


```
ArrayList a = new ArrayList();
        ArrayList b = new ArrayList();
        
        a.add("Hallo");
        a.add(100);
        b = a;
        b.add("noch ein neues Element");
        
        Iterator it = a.iterator();
        while(it.hasNext()) {
            System.out.println(it.next());
        }
```

- Korrekt, weil b(genauso wie a) auf den gleichen Wert im Heap zeigen. Und nun addiert b etwas
zu diesem 'Bereich' im Heap dazu. Also hat auch a diesen dazu bekommen. Bei elementaren Werten passiert
dieses nicht, weil die keinen "Zeiger" auf den Heap haben. Bei nicht elementaren Werten(Array,Objekte, ArrayListen etc.)
hingegen schon... und genau DESHALB habe ich nun gefragt, warum es bei Strings wohl nicht so ist und diese
sich ähnlich wie elementare Datentypen verhalten.

Das liegt wohl daran das diese immutable sind... also sorry, aber ich finde das alles nicht so trivial!! Und habe langsam
die Vermutung das einige von euch das auch nicht wissen, aber direkt abklatschen mit "nein soetwas gibst in java garnicht...."


----------



## Gast2 (19. Jul 2012)

Du beschreibst einen komplett anderen Sachverhalt als Mujahiddin 

Mujahiddin hat dir gezeigt dass es in Java kein call-by-referrnce gibt (das ändern der (kopierten) Referenz hat keine Auswirkungen auf den Aufrufer).

Du hingegen hast "nur" gezeigt dass wenn zwei Variablen auf das gleiche Objekt zeigen, beide das selbe Objekt verändern, was ja eigentlich auch klar und logisch ist. Wäre das nicht so würde man sich ganz schön schwer tun beim programmieren 

Wie oben schon erwähnt, mit immutable und nicht-immutable bist du da aufm falschen Dampfer, das hat damit wenig zu tun.


----------



## b1zarRe (19. Jul 2012)

Und warum hat 


```
public static void main(String[] args) {

       ArrayList a = new ArrayList();
        a.add("Hallo");
        a.add(100);
        
        machWas(a);
        
        Iterator it = a.iterator();
        while(it.hasNext()) {
            System.out.println(it.next()); //Output: Hallo, 100, ganz neu ---> Würde man nun die ganze Sache mit elementaren Typen, wie zb. int anstelle ArrayList realisieren, hätte die Methode KEINE Änderungen für das ursprüungliche int gemacht !!!!!!
        }
    }
    
    public static void machWas(ArrayList neu) {
        neu.add("ganz neu");
    }
}
```

die kopierte Referenz sehr wohl Auswirkung auf den Aufrufer???


----------



## Gast2 (19. Jul 2012)

Weil beide auf das selbe Objekt zeigen


----------



## b1zarRe (19. Jul 2012)

Korrekt. *Deshalb *wollte ich wissen, warum es bei Strings NICHT so geht !


----------



## Gast2 (19. Jul 2012)

Was genau meinst du denn mit "es"?

Bei der ArrayList änderst du mit dem add die "inneren Daten" der ArrayList instanz. Einen String kannst du nicht ändern. Deshalb ist das Beispiel auf Strings nicht übertragbar.

Könnte man Strings ändern, bspw. mit einer setCharAt() Methode könnte man das Beispiel auch 1 zu 1 auf Strings übertragen.


----------



## b1zarRe (19. Jul 2012)

Jawohl... und deshalb zitiere ich dich nochmal:
"Wie oben schon erwähnt, mit immutable und nicht-immutable bist du da aufm falschen Dampfer, das hat damit wenig zu tun."
Also, hat dies sehr wohl was mit immutable(und in den anderen Fällen ob elementarer Datenyp bzw. nicht elemntar) zu tun 
- Mehr wollte ich nicht wissen... habe das ganze als CallByReference Effekt benannt, weil der Prof. das in der Vorlesung auch so benannt hatte.... Und muss sagen, das mir meine Codes nun soweit klar sind.

Was mir dagegen nichtmehr ganz so klar ist, ist was nun genau CallByReference ist, wenn es das nicht ist, was ich genannt habe.
Der Link "CallByValue/CallByReference" habe ich mir schon zugemüte geführt... bringt mich allerdings nicht wirklich weiter... jendefalls nicht 100 Prozent:

Ein Beispiel aus dem Link


```
public static void main(String[] args){
		Integer i = new Integer(1);
		Integer j = new Integer(2);
		System.out.println(i + " " + j);
		swap(i,j);
		System.out.println(i + " " + j);
	}
	
	public static void swap(Integer i, Integer j) {
		Integer tmp = i;
		i = j;
		j = tmp;
	}
```

Hier wird nun gesagt, dass beides mal 1 2 herauskommt. Also es kein CallByReference gibt(!= einer ähnlichen Umsetzung in C),
ABER: kann man das überhaupt so vergleichen??? Integer ist nämlich der Wrapper für ein int.. Also eine Hülle welche auch nur ein int in sich trägt. Meiner Meinung nach wird genau DESHALB zweimal 1 2 ausgegeben. Man möge das Beispiel doch mit ArrayListen oder Arrays machen... ich glaube dann sieht das ganze anders aus...... - deshalb ist dieses FAQ hier aus dem Forum entweder falsch oder ich steige da noch nicht 100 Pro durch.


----------



## Gast2 (19. Jul 2012)

> Jawohl... und deshalb zitiere ich dich nochmal:
> "Wie oben schon erwähnt, mit immutable und nicht-immutable bist du da aufm falschen Dampfer, das hat damit wenig zu tun."
> Also, hat dies sehr wohl was mit immutable(und in den anderen Fällen ob elementarer Datenyp bzw. nicht elemntar) zu tun


Nur weil Äpfel rund sind, heißt das nicht dass alles was rund ist nen Apfel sein muss.

Zu deinem Beispiel. Probiers einfach mit irgend einer beliebigen Klasse, erstelle dir selbst eine Klasse. Du wirst immer das selbe verhalten feststellen, eben weil es in Java nunmal kein call-by-reference gibt 



> [...] oder ich steige da noch nicht 100 Pro durch


Ich tippe auf diesen Fall


----------



## hüteüberhüte (19. Jul 2012)

Edit: Durch eine Zuweisung (weil call-by-value) lässt sich kein Objekt ändern. Ich hab früher in Grundlagenvorlesung gelernt, eine Zuweisung weist einer Variablen einen Wert zu, nicht mehr, nicht weniger. Und der Wert ist bei einer Referenzvariablen eine Referenz

Edit2: Siehe nächsten Beitrag (Sry, Doppelpost)


----------



## hüteüberhüte (19. Jul 2012)

Ok, in der JLS steht etwas darüber: Types, Values, and Variables


> Method parameters (§8.4.1) name argument values passed to a method. For every parameter declared in a method declaration, a new parameter variable is created each time that method is invoked (§15.12). The new variable is initialized with the corresponding argument value from the method invocation. The method parameter effectively ceases to exist when the execution of the body of the method is complete.



Also die Variable (der formale Parameter) wird mit dem Wert des Arguments initialisiert

Bin mir sicher, es wird auch noch etwas mehr darüber stehen. Explizit "call-by-value" bzw. "pass-by-value" habe ich jetzt nicht gefunden, aber es wird genau dieser Vorgang beschrieben


----------



## AngryDeveloper (19. Jul 2012)

b1zarRe hat gesagt.:


> ABER: kann man das überhaupt so vergleichen??? Integer ist nämlich der Wrapper für ein int.. Also eine Hülle welche auch nur ein int in sich trägt. Meiner Meinung nach wird genau DESHALB zweimal 1 2 ausgegeben. Man möge das Beispiel doch mit ArrayListen oder Arrays machen... ich glaube dann sieht das ganze anders aus...... - deshalb ist dieses FAQ hier aus dem Forum entweder falsch oder ich steige da noch nicht 100 Pro durch.



Dann mach das Beispiel doch mit z.B. ArrayList. Ist doch Jacke wie Hose:

```
public static void main(String[] args){
    ArrayList i = new ArrayList();
    i.add("1");
    ArrayList j = new ArrayList();
    j.add("2");
    System.out.println(i.get(0) + " " + j.get(0));
    swap(i,j);
    System.out.println(i.get(0) + " " + j.get(0));
}
	
public static void swap(ArrayList i, ArrayList j) {
    ArrayList tmp = i;
    i = j;
    j = tmp;
}
```
Ausgabe ist beide male 1 2

Wenn du das wirklich swappen wollen würdest, dann müsstest du das erste Element in der Datenstruktur austauschen. Dies ist dann aber ein ganz anderer Fall, weil da etwas ganz anderes passiert.

Java -> nur Call by Value
Java is Pass-by-Value, Dammit! - Scott Stanchfield


----------



## b1zarRe (19. Jul 2012)

Du hast recht: Beide mal 1 2 ... Aber warum??? Kann mir das jemand evtl. erklären und sagen, was Da schritt für schritt mit Stack/Heap passiert???


```
int[] i = {1};
    System.out.println(i[0]);
    change(i);
    System.out.println(i[0]);
}
    
    public static void change(int[] i) {
        i[0]=10;
    }
}
```
Warum wird denn hier das anfängliche Array verändert?! Müsste da bei
der 2. Ausgabe dann nicht auch "nur" 1 herauskommen?!?!


----------



## Gast2 (19. Jul 2012)

Lass doch den Stack einfach mal Stack sein. Es reicht wenn du dir vorstellst dass es irgendwo ein Objekt gibt und irgendwo ander eine Variable die auf dieses Objekt zeigt.

Vergleich mal doch die beiden kritischen Stücke:

```
public static void swap(Integer i, Integer j) {
    Integer tmp = i;
    i = j;
    j = tmp;
}
```
und

```
public static void change(int[] i) {
     i[0]=10;
}
```
Beim ersten mal tauschst du nur die Objekte aus auf die i bzw. j zeigen. Das hat auf den Aufrufer aber keine Auswirkungen.
Beim zweiten mal hast du zwei Referenzen die auf dein Array (Objekt) zeigen. Einmal die Referenz des Aufrufers, und zum anderen die Referenz in der Methode. Jetzt änderst du das Objekt in der Methode, das bekommt der andere natürlich mit.


----------



## AngryDeveloper (19. Jul 2012)

Weil das 2 grundlegend verschiedene Dinge sind. Siehe wiederum:

```
public static void main(String[] args) {
    int[] i = {1};
    int[] j = {2};
    System.out.println(i[0] + " " + j[0]);
    swap(i, j);
    System.out.println(i[0] + " " + j[0]);
}
    
public static void swap(int[] i, int[] j) {
    int[] tmp = i;
    i = j;
    j = tmp;
}
```

Bei dem einen veränderst du den *Inhalt *eines Objekts (das Objekt ist in diesem Fall das Array, der Inhalt ist der Wert an Index 0). Bei Arrays wird der Zeiger übergeben und keine komplette Kopie des Arrays.

Bei dem anderen veränderst du die Adresse auf die die Variable zeigt. Dieser Zeiger wird allerdings bei der Übergabe kopiert. Weißt du dieser Kopie einen neuen Zeiger/Adresse zu, ändert sich ja nicht der Zeiger der Variable die du übergeben hast.

Java macht es hierbei wie C und den Pointern (*): Call by Value.
Nicht wie C++ bei Referenzen (&): Call by Reference.


----------



## b1zarRe (19. Jul 2012)

Okay danke...
glaube mein Fehler war zu denken, dass "=" das selbe macht in jeder Situation, wobei es klar ist, dass

1) int a = 10;

was anderes ist als

2) ArrayList a = new ArrayList();
ArrayList b = a;

Beim ersten wieder der Wert verändert und beim zweiten der Zeiger, korrekt?


----------



## andiv (19. Jul 2012)

Um den Unterschied zwischen Call by Value und Call by Reference zu verstehen, kann es sich lohnen eine Sprache zu betrachten, die auch wirklich beide Varianten unterstützt. Ich wähle dazu C++:


```
// [1] Normale Variable vom Typ "Foo" mit Namen "var"
Foo var;
// es wird automatisch der Konstruktor von Foo aufgerufen

// [2] Zeiger auf eine Variable vom Typ "Foo" mit dem Namen "ptr"
Foo* ptr = &var;
// dem Zeiger muss die Adresse einer Variable vom Typ "Foo" zugewiesen werden

// [3] Zeiger auf einen Zeiger auf eine Variable vom Typ "Foo" mit Namen "dblptr"
Foo** dblptr = &ptr;
// dem Zeiger muss die Adresse eines Zeigers auf eine Variable vom Typ "Foo" zugewiesen werden

// [4] Referenz auf eine Variable vom Typ "Foo" mit Namen "ref"
Foo& ref = var;
// der Referenz muss eine Variable vom Typ "Foo" zugewiesen werden
```

Das besondere an der Referenz ist, dass "ref" ein Alias für "var" ist. Ob man ref oder var schreibt ist egal, beides meint die gleiche Variable. Im Gegensatz dazu ist der Wert von "ptr" die Adresse von "var" und damit ein anderer als der Wert von "var".


```
// [5] Beim Aufruf von "callByValue" werden die Variablen kopiert
void callByValue(Foo var1, Foo var2) {
    Foo tmp = var1;
    var1 = var2;
    var2 = tmp;
}

// "var1" und "var2" sind nach Aufruf der Funktion unverändert
Foo var1;
Foo var2;
callByValue(var1, var2);

// [6] Beim Aufruf von "callByValue2" werden die Zeiger kopiert
void callByValue2(Foo* ptr1, Foo* ptr2) {
    Foo* tmp = ptr1;
    ptr1 = ptr2;
    ptr2 = tmp;
}

// "ptr1" und "ptr2" sind nach Aufruf der Funktion unverändert
Foo ptr1 = &var1;
Foo ptr2 = &var2;
callByValue(ptr1, ptr2);

// [7] Beim Aufruf von "callByValue3" werden die Zeiger kopiert, aber es werden nicht die Kopien verändert, sondern die Variablen auf die sie zeigen
void callByValue3(Foo* ptr1, Foo* ptr2) {
    Foo tmp = *ptr1;
    *ptr1 = *ptr2;
    *ptr2 = &tmp;
}

// "ptr1" und "ptr2" sind nach Aufruf der Funktion unverändert, aber die Variablen auf die sie zeigen, also "var1" und "var2" wurden verändert
callByValue(ptr1, ptr2);

// [8] Beim Aufruf von "callByReference" werden die Variablen nicht kopiert! "ref1" ist ein Alias für die übergebene Variable
void callByReference(Foo& ref1, Foo& ref2) {
   Foo tmp = ref1;
   ref1 = ref2;
   ref2 = tmp;
}

// "var1" und "var" sind nach Aufruf der Funktion verändert
callByReference(var1, var2);
```

Wie verhält sich das ganze nun in Java?
Ist Foo einer der Typen byte, short, int, long, char, float oder double, dann entspricht das dem Fall [1] in C++.
Ist Foo vom Typ Object oder einer anderen Klasse wie String, int[] oder ArrayList, dann entspricht das dem Fall [2] in C++ und wir haben es die ganze Zeit mit einem Zeiger auf eine Variable zu tun. Den * braucht man in Java nicht, da durch den Typ der Variable direkt klar ist ob wir einen Zeiger haben oder nicht. Die Möglichkeit von Zeigern auf Zeiger oder höheres [3] gibt es genausowenig wie richtige Referenzen [4] die als Alias wirken.


```
// [9] Beim Aufruf von "callByValue" werden die Variablen kopiert
void callByValue(int var1, int var2) {
    int tmp = var1;
    var1 = var2;
    var2 = tmp;
}

// "var1" und "var2" sind nach Aufruf der Funktion unverändert
int var1;
int var2;
callbyValue(var1, var2);

// [10] Beim Aufruf von "callByValue2" werden die Zeiger kopiert
void callByValue2(int[] ptr1, int[] ptr2) {
    int[] tmp = ptr1;
    ptr1 = ptr2;
    ptr2 = tmp;
}

// "ptr1" und "ptr2" sind nach Aufruf der Funktion unverändert
int[] ptr1 = {1};
int[] ptr2 = {2};
callByValue2(ptr1, ptr2}

// [11] Beim Aufruf von "callByValue3" werden die Zeiger kopiert, aber es werden nicht die Kopien verändert, sondern die Variablen auf die sie zeigen
void callByValue3(int[] ptr1, int[] ptr2) {
    int tmp = ptr1[0];
    ptr1[0] = ptr2[0];
    ptr2[0] = tmp;
}

// "ptr1" und "ptr2" zeigen nach Aufruf der Funktion weiter auf die gleichen Objekte, aber der Inhalt der Objekte wurde verändert
callByValue(ptr1, ptr2);
```

Der Fall [9] in Java entspricht genau dem Fall [5] in C++.
Der Fall [10] in Java entspricht dem Fall [6] in C++, um den Zeiger selbst zu verändern müsste man entweder einen Zeiger auf einen Zeiger übergeben (call-by-value-Variante) oder eine Referenz auf einen Zeiger (call-by-reference-Variante), in Java ist so etwas nicht möglich.
Der Fall [11] entspricht dem Fall [7] in C++, wir lassen uns einen Zeiger übergeben und verändern das Objekt auf das er zeigt. Diese Wirkung ist auch von außen sichtbar.
Etwas analoges zu Fall [8] gibt es in Java nicht, denn Java kennt kein "call-by-reference".

Was ist das besondere an "immutable" Objekten in Java? Variante [10] ist bekanntlich wirkungslos und Variante [11] unmöglich, da das Objekt auf das "ptr" zeigt keine Möglichkeit zur Veränderung bietet. Der Außenstehende hat also das Gefühl er hätte es mit Variante [9] zu tun.

Was soll nun der "call-by-reference"-Effekt sein? Wenn Variante [11] mit einem "mutable"-Objekt verwendet wird, dann ist nach außen eine Wirkung sichtbar. Den Außenstehenden erinnert der Funktionsaufruf nun an Variante [8] aus C++ (richtiges Call by Reference), in Wahrheit haben wir es aber mit Fall [7] aus C++ zu tun (Call by Value).

Die Verständnisprobleme sind also nur deshalb da, weil Java nicht durch zusätzliche Syntax deutlich macht, wann wir mit normalen Variablen und wann mit Zeigern herum hantieren.


----------



## hüteüberhüte (19. Jul 2012)

b1zarRe hat gesagt.:


> Okay danke...
> glaube mein Fehler war zu denken, dass "=" das selbe macht in jeder Situation, wobei es klar ist, dass
> 
> 1) int a = 10;
> ...



Ja, das ist korrekt. In Java gibt es aber kein Alias, weil immer ein Kopie des Werts erstellt wird und den Parametern zugewiesen wird. Außerdem gibt es keine Zeiger/Referenzen auf selbige


----------



## Mujahiddin (20. Jul 2012)

Ist das auch der Grund, dass es so schnell zum StackOverflowError kommt bei rekursiven Funktionen?


----------



## bone2 (20. Jul 2012)

Das liegt eher daran, wieviel speicher die java lässt


----------

