primitive Variablen auf Umweg doch über Methode ändern

MichiM

Mitglied
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
 
Also den int-Wert bestimmen kannst du mit
Code:
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:
Code:
 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
 
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:
Code:
    /**
     * 
     */
    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...).
 
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.

Wenn ja Call by Reference erlauben würde dann könnte man ja folgendes machen:
Code:
  /**
   * 
   */
  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.


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...).
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
 
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
 
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:
Code:
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):
Code:
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
 
Zuletzt bearbeitet:
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.

Code:
   #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
 
Also mit den Sachen habs ichs ja nicht so, deshalb frag ich noch mal nach:

Code:
 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:
Code:
 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?
 
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:
Code:
#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:

Code:
#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
 
Zurück