# primitive Variablen auf Umweg doch über Methode ändern



## MichiM (18. November 2005)

Hi,

nun werden primitive Variablen also "by value" übergeben und Objekte "by reference".
Wie lässt sich denn dann der Wert so einer primitiven Variable - eben über einen Umweg - doch über eine Methode ändern?
Erzeuge ich ein Wrapper-Objekt (aus int mach Integer), dann wären zwar nun die Voraussetzungen für eine Änderung gegeben, ich weiß jedoch nicht, mit welcher Methode bzw. Zuweisung. Dazu fehlt mir sowas wie eine Instanz "Integer.value" bzw. eine Methode Integer.setValue();   

Wie geht das?

Ciao!
MichiM


----------



## javaprogger1987 (18. November 2005)

Also den int-Wert bestimmen kannst du mit 
	
	
	



```
intValue()
```
.
 Hab mal ein bischen damit rumgetestet, aber es nicht geschafft den Integer zu ändern (Verhält sich wie ein primitiver Datentyp ?)
 Kannst es mit ner Hilfsklasse machen:

```
class Wrapper
 {
   private int i;
   
   public Wrapper( int i )
   {
 	this.i = i;
   }
   
   public Wrapper()
   {	
   }
   
   public void setInt( int integer )
   {
 	i = integer;
   }
   
   public int getInt()
   {
 	return i;
   }
 }
```
 
 mfg

 Tobias


----------



## Thomas Darimont (19. November 2005)

Hallo!



> Hi,
> 
> nun werden primitive Variablen also "by value" übergeben und Objekte "by reference".


 Das ist nicht richitg. In Java werden alle Werte per Value übergeben. Sowohl Primitive als auch Referenztypen. Bei Referenztypen wird die Referenz per Value übergeben. Dabei wird die Referenz kopiert, nicht aber das Objekt das referenziert wird.

    Wenn Java Call by Reference erlauben würde dann könnte man ja folgendes machen:

```
/**
     * 
     */
    package de.tutorials;
    
    /**
     * @author Tom
     *
     */
    public class FaultyByRefenceExample {
    
    	/**
    	 * @param args
    	 */
    	public static void main(String[] args) {
    		String s = "foo";
    		bar(s);
 		System.out.println(s); //Würde bar Ausgeben... //gibt aber, korrekter Weise, foo aus.
    	}
    
    	private static void bar(String s) {
    		s = "bar";
    	}
    }
```
     Ein Call by Reference gibt es beispielsweise in C/C++... aber wie gesagt nicht in Java.



> Wie lässt sich denn dann der Wert so einer primitiven Variable - eben über einen Umweg - doch über eine Methode ändern?


 Nur indem man den primitiven Wert in einen nicht primitiven Wert kapselt... und diesen dann Mutable macht. Integer als Wrapper ist beispielsweise immutable also unveränderlich. Du findest also keine Setter Methode im den gekapselten int Wert zu manipulieren (es geht aber per Reflection...).


----------



## MichiM (19. November 2005)

Thomas Darimont hat gesagt.:
			
		

> Hallo!
> 
> 
> Das ist nicht richitg. In Java werden alle Werte per Value übergeben. Sowohl Primitive als auch Referenztypen. Bei Referenztypen wird die Referenz per Value übergeben.
> ...


 Dachte: "Is bestimmt recht einfach und ich komm nur grad nicht drauf", aber so einfach ist es scheinbar doch nicht.  Gut, dann muss ich eben ggf. eine Schnittstelle schaffen.

Danke Euch!
MichiM


----------



## RedWing (20. November 2005)

Hallo,


> Ein Call by Reference gibt es beispielsweise in C/C++... aber wie gesagt nicht in Java.



auch auf die Gefahr hin das ich jetzt Haare spalte aber ich muss das dennoch
berichtigen. In C gibt es kein call by reference. Das wurde erst in C++ 
eingeführt... In C gibt es nur das call by value (ähnlich wie in Java) und zwar in
dem die Pointer per value übergeben werden.

Gruß

RedWing


----------



## Thomas Darimont (20. November 2005)

Hallo!

 ich dachte das gaebs auch unter C, in dem man an eine Funktion einfach die Adressen (mit &var) uebergibt und dann darueber den Inhalt  manipuliert.
 Siehe auch hier:
http://www.cs.bris.ac.uk/Teaching/Resources/COMS11401/3_Parameter_Passing.p.pdf 

 Gruss Tom


----------



## RedWing (20. November 2005)

Hallo,
//offtopic
Mhm also ich verstehe unter call by reference das man eine Adresse 
übergibt und dann mit dem Parameter innerhalb der Funktion wie mit einem
ganz normalen Objekt arbeiten kann und auch an die Referenz erst gar nicht ran kommt.

So etwas wäre in C++ für mich call by reference:

C++ Call by reference:

```
void swap(int& a, int& b){  //die adressen koennen nicht veändert werden
       int tmp = a; //hier wird ganz normal mit den Objekten gearbeitet
       a = b;
       b = tmp;
}
...
int a = 3, b = 2;
swap(a,b);
```

In C (meiner Ansicht nach zu unrecht call by reference genannt wie im pdf, da man direkten zugriff auf die adressen hat):

```
void swap(int* a, int* b){ //hier können die adressen verändert werden siehe java Bsp von Thomas
      int tmp = *a; //hier muss erst derefernziert werden
      *a = *b;
      *b = tmp;
}
...
int a = 3, b = 2;
swap(&a, &b); //hier werden die Adressen per Value übergeben
```

P.S. In dem pdf steht auch 


> To get the effect of “Call-by-Reference” in C:


Gruß

RedWing


----------



## Thomas Darimont (20. November 2005)

Hallo!

 Okay, deine Argumente sehe ich ein, jedoch ist das letztendliche Resultat genau das was der OP "moechte". Weiterhin heisst das doch, dass man auch unter C Call by Reference Semantik erhalten kann auch wenns eigentlich kein "richtiges" Call by Reference ist. In Java geht das nicht.


```
#include <stdio.h>
   #include <stdlib.h>
   
   
   void foo(int* value){
      *value = 99;	 
   }
   	 
   
   int main(int argc, char *argv[])
   {
     int a = 1;
     printf("a= %d\n",a);
     foo(&a);
     printf("a= %d\n",a);
   	
     system("PAUSE");	
     return 0;
   }
```
 
   Gruss Tom


----------



## javaprogger1987 (20. November 2005)

Also mit den Sachen habs ichs ja nicht so, deshalb frag ich noch mal nach:


```
public class Primitives
 {
   public Primitives()
   {
 	Wrapper w = new Wrapper( 1 );
 	changeToZero( w );
 	System.out.println( w.getInt() );
   }
 
   private void changeToZero( int i )
   {
 	i = 0;
   }
 
   private void changeToZero( Wrapper w )
   {
 	w.setInt( 0 ); // So gehts
 	w = new Wrapper( 0 ); // So gehts nicht
   }
 
   public static void main( String[] args )
   {
 	Primitives primitives = new Primitives();
   }
 }
```
 
 Wrapper:

```
class Wrapper
  {
    private int i;
  
    public Wrapper( int i )
    {
  	this.i = i;
    }
  
    public Wrapper()
    {
    }
  
    public void setInt( int integer )
    {
  	i = integer;
    }
  
    public int getInt()
    {
  	return i;
    }
  }
```
 
 Meine Frage ist nun, warum die markierte Stelle einmal funktioniert und einmal nicht. Ist das so, weil die Variable quasi ein Pointer auf das Objekt, und bei der new Zuweisung wird dann der Pointer auf ein neues Objekt gesetzt?


----------



## RedWing (20. November 2005)

Naja wenns um die Semantik geht würde ich sagen das dein C Beispiel
äquivalent mit javaprogger87s Wrapper ist. Bei beidem wird die Adresse
call by value übergeben und bei beidem wird "dereferenziert".

Vielleicht dein java Bsp in C koennte das auch nochmal deutlich machen 
das es eben in C,wie du schon sagtest, kein richtiges call by reference gibt:

```
#include <stdio.h>

void bar(char* s) {
    s = "bar";
}

int main() {
    char* s = "foo";
    bar(s);
    printf("%s\n", s); //Würde bar Ausgeben... //gibt aber, korrekter Weise, foo aus.
}
```

Man koennte das umgehen in dem man vielleicht sagt:


```
#include <stdio.h>
void bar(char** s) {
    *s = "bar";
}

int main() {
    char* s = "foo";
    bar(&s);
    printf("%s\n", s); //gibt korrekter Weise bar aus
}
```

Aber auch das koennte man meiner Ansicht nach in Java durch einen 
Wrapper abbilden oder?

Gruß

RedWing


----------



## RedWing (20. November 2005)

> Meine Frage ist nun, warum die markierte Stelle einmal funktioniert und einmal nicht. Ist das so, weil die Variable quasi ein Pointer auf das Objekt, und bei der new Zuweisung wird dann der Pointer auf ein neues Objekt gesetzt?



Das liegt eben daran wie Tom schon sagte das die Referenz bzw der 
Referenztyp auch call by value übergeben wird (sprich bei der Übergabe 
kopiert wird). Wenn du nun mit new ne neue Zuweisung an deine Referenz 
machst, ändert das die Referenz aber nicht das Objekt auf das die 
ursprüngliche  Referenz zeigte. => dein objekt vor dem Aufruf bleibt 
unverändert.

Gruß

RedWing


----------



## RedWing (20. November 2005)

//nochmal offtopic

Hab grad noch a bisl rumgespielt (just for info). 
Korrektes call by reference in C++ (was in Java und C so nicht geht)
würde so aussehen:


```
#include <iostream>

using namespace std;

void bar(char*& s) {
    s = "bar";
}

int main() {
    char* s = "foo";
    bar(s);
    cout << s << endl; //gibt korrekter Weise bar aus
}
```

Gruß

RedWing


----------

