call by reference

incsoft

Grünschnabel
Hallo,

ich habe mal eine Frage zu call by reference. Folgendes Codestück habe ich geschrieben:

public class test
{

public static void main(String[] args)
{

String str = "Hallo";

funktion(str);

System.out.println(str);

}

public static void funktion(String str)
{

str = "Welt!";

}

}

Ich hatte eigentlich gedacht, dass er dann "Welt!" ausgibt, aber er gibt "Hallo" aus (JDK 1.4.2.01. Wie bekommt man es nun hin, dass nach dem Aufruf der Methode funktion() in der Variablen str die Zeichenkette "Welt!" steht?

Vielen Dank und MfG

incsoft
 
incsoft hat gesagt.:
Hallo,

ich habe mal eine Frage zu call by reference. Folgendes Codestück habe ich geschrieben:

Code:
public class test
{
	public static void main(String[] args)
	{
		String str = "Hallo";
		funktion(str);
		System.out.println(str);
	}
	
	public static void funktion(String str)
	{
		str = "Welt!";
	}
}

Ich hatte eigentlich gedacht, dass er dann "Welt!" ausgibt, aber er gibt "Hallo" aus (JDK 1.4.2.01. Wie bekommt man es nun hin, dass nach dem Aufruf der Methode funktion() in der Variablen str die Zeichenkette "Welt!" steht?

Vielen Dank und MfG

incsoft

Ein einfacher Weg ist z.B. statt funktion(str); dieses hier:

str = funktion(str);

mit

Code:
public static String funktion(String str)
{
  return "Welt!";
}

BTW Klassennamen beginnen mit einem Großbuchstaben.
 
Hi,

das war eigenltich nur ein Beispiel. So wie du es geschrieben hast, ist es ja dann kein call by reference mehr. Ich brauche das für die Rückgabe von zwei Werten (durch eine Funktion).

Hier mal das konkrete Problem:
Code:
class Signal
{
	
	public static final int KEIN_SIGNAL = 0;
	public static final int NEUE_AKTUELLE_ZAHL = 1;
	public static final int HINZU_NEUE_PRIMZAHL = 2;
	public static final int BUTTON_TEXT_AENDERN = 3;
	
	private int signal = KEIN_SIGNAL;
	private String wert = null;
	
	//setzt ein bestimmtes Signal und den Wert
	public synchronized void setSignal(int signal, String wert)
	{
		
		try
		{
				
			while(this.signal != KEIN_SIGNAL)
				wait();
			
			this.signal = signal;
			this.wert = wert;
			
			System.out.println("Wert auf " + wert + " gesetzt.");
			
			this.notify();
			
		}
		catch(Exception e)
		{ /* nichts */ }
		
	}
	
	//gibt den Signaltyp (als int) zurück
	//der Wert wird per call-by-reference zurückgegeben
	public synchronized int getSignal(String wert)
	{
		
		try
		{
			
			while(this.signal == KEIN_SIGNAL)
				wait();
			
			int hilf = this.signal;
			this.signal = KEIN_SIGNAL;
			System.out.println("Lesen von this.wert in getSignal: " + this.wert);	
			wert = new String(this.wert);
			System.out.println("Lesen von wert in getSignal: " + wert);
			
			this.notify();
			
			return hilf;
			
		}	
		catch(Exception e)
		{ /* nichts */ }
		
		return 0;
		
	}
	
}
Der Aufruf soll dann mit
Code:
	//innere Klasse
	//Thread zur Ausgabe der (Zwischen)Ergebnisse des Berechnungs-Thread
	class Ausgabe extends Thread
	{
		
		Signal signal = null;
		
		//dem Konstruktor wird das Signalobjekt übergeben, über
		//welches die Synchronisation erfolgt
		public Ausgabe(Signal s)
		{
			
			this.signal = s;
			
		}
		
		public void run()
		{
			
			while(!isInterrupted())
			{
				
				String wert = null;
				int sig = signal.getSignal(wert); // <-- HIER
				
				//prüfen welches Signal empfangen wurde
				//und entsprechend reagieren
				switch(sig)
				{
					
					case Signal.NEUE_AKTUELLE_ZAHL:
						aktualisiereAktuelleZahl(wert);
						break;
						
					case Signal.HINZU_NEUE_PRIMZAHL:
						aktualisiereAusgabeFeld(wert);
						break;
						
					case Signal.BUTTON_TEXT_AENDERN:
						aktualisiereButtonText(wert);
						break;
										
				} //switch
			
				
			} //while
			
		} //run
		
	} //class Ausgabe
erfolgen.

Danke und MfG

incsoft
 
Ich lese vor aus dem Handbuch der Java-Programmierung, Kapitel 7.3.3:

"Alle Parameter werden in Java per call by value übergeben. Beim Aufruf einer Methode wird also der aktuelle Wert in die Parametervariable kopiert und an die Methode übergeben. Veränderungen der Parametervariablen innerhalb der Methode bleiben lokal und wirken sich nicht auf den Aufrufer aus."
...
"Wie bereits erwähnt, sind Objektvariablen Referenzen, also Zeiger. Zwar werden auch sie bei der Übergabe an eine Methode per Wert übergeben. Da innerhalb der Methode aber der Zeiger auf das Originalobjekt zur Verfügung steht (wenn auch in kopierter Form), wirken sich Veränderungen an dem Objekt natürlich direkt auf das Originalobjekt aus und sind somit für den Aufrufer der Methode sichtbar. Wie in allen anderen Programmiersprachen entspricht die call by value-Übergabe eines Zeigers damit natürlich genau der Semantik von call by reference."
 
Snape hat gesagt.:
"Wie bereits erwähnt, sind Objektvariablen Referenzen, also Zeiger. Zwar werden auch sie bei der Übergabe an eine Methode per Wert übergeben. Da innerhalb der Methode aber der Zeiger auf das Originalobjekt zur Verfügung steht (wenn auch in kopierter Form), wirken sich Veränderungen an dem Objekt natürlich direkt auf das Originalobjekt aus und sind somit für den Aufrufer der Methode sichtbar. Wie in allen anderen Programmiersprachen entspricht die call by value-Übergabe eines Zeigers damit natürlich genau der Semantik von call by reference."
Und genau das ist auch so. Dass es bei dem String-Beispiel nicht wie gewünscht funktioniert liegt einzig und allein an der Unveränderbarkeit von Strings.
Diese Unveränderbarkeit sorgt dafür, dass bei dieser Zeile:
Code:
str = "Welt!";
ein neues String Objekt mit dem Inhalt "Welt!" erzeugt und dessen Adresse in die lokale Variable str geschrieben wird, wodurch natürlich die Referenz auf das ursprüngliche Objekt verloren geht.
Machbar wäre dein Vorhaben mit jedem Objekt, welches du nur veränderst und nicht ersetzt, also z.B. mit einem StringBuffer:
Code:
public class Test
{
  public static void main(String[] args)
  {
    StringBuffer str = new StringBuffer("Hallo");
    funktion(str);
    System.out.println(str);
  }
  
  public static void funktion(StringBuffer str)
  {
    str.delete(0, str.length());
    str.append("Welt!");
  }
}
Gruß Peter
 
Code:
private void init() {
  String[] s = {"Heinz"};
  change(s);
  System.out.println(s[0]); //"Max"
}
 
private void change(String[] s) {
  s[0] = "Max";
}

CU schnuffie
 

Neue Beiträge

Zurück