Funktionsaufruf und Parameterübergabe in Java



  • Jetzt müsst ihr mir aber mal erklären warum sich das bei Objekten By-Value nennt wenn doch die Referenz übergeben wird. Für mich sieht das nach Call-By-Reference aus



  • Tolpan schrieb:

    Jetzt müsst ihr mir aber mal erklären warum sich das bei Objekten By-Value nennt wenn doch die Referenz übergeben wird. Für mich sieht das nach Call-By-Reference aus

    'ne java-referenz ist eine variable, die verweise auf objekte speichern kann. weil der inhalt dieser variablen (der 'value') kopiert wird, ist es technisch 'call by value', von der bedeutung aber 'call by reference'. je nachdem, aus welcher perspektive du's betrachtest.
    🙂



  • Es ist kein Call-by-Reference. Die Werte werden beim Übergeben kopiert, auch wenn das zufällig Referenzen sind, es bleibt Call-by-Value.
    Versuch doch mal in Java, eine swap-Methode zu schreiben.



  • Aber wenn ich eine Referenz "echt" übergebe muss ich sie doch auch ändern können und damit bin ich wieder bei Pointern oder nicht.



  • Was heißt "echt" übergeben?
    Ändern kannst du Parameter-Variable innerhalb der Methode. Diese Änderung lebt aber nur innerhalb der Methode.



  • Ich frag lieber mal so rum: Was ist denn dann Call-By-Referenz??



  • tfa schrieb:

    Versuch doch mal in Java, eine swap-Methode zu schreiben.

    sowas?

    void swap (int[] a)
    {
       int tmp = a[0];
       a[0] = a[1];
       a[1] = tmp;
    }
    ...
    int[] a = {1,2};
    swap (a);
    ...
    

    🙂



  • Tolpan schrieb:

    Ich frag lieber mal so rum: Was ist denn dann Call-By-Referenz??

    http://computer-programming-tutorials.suite101.com/article.cfm/program_for_swapping_integers_in_c



  • Mal gucken ob ich das jetzt verstanden hab.

    dein Artikel sagt mir, dass ich in C in der Lage bin die Referenzen von primitiven Typen zu vertauschen. Das ist mir klar. Genauso klar ist das das in Java nicht geht. Aber ich kann doch in Java folgendes tun: Ich habe ein zwei Objekte. Die Referenzen liegen in Object a und Object b. Wenn ich nun eine Swap Methode schreibe und diese ausführe habe ich danach die Referenz die vorher in a war in b und umgekehrt. Also das gleiche, was C auch mit Primitven kann.

    Mir ist einfach nicht Klar warum das kein CallBy-Ref ist?



  • tfa schrieb:

    http://computer-programming-tutorials.suite101.com/article.cfm/program_for_swapping_integers_in_c

    aber im kommentar stehts richtig.
    Tolpan: in java müssen deine objekte 'mutable' sein, damit sowas funktioniert.
    🙂



  • Tolpan schrieb:

    Aber ich kann doch in Java folgendes tun: Ich habe ein zwei Objekte. Die Referenzen liegen in Object a und Object b. Wenn ich nun eine Swap Methode schreibe und diese ausführe habe ich danach die Referenz die vorher in a war in b und umgekehrt. Also das gleiche, was C auch mit Primitven kann.

    Mir ist einfach nicht Klar warum das kein CallBy-Ref ist?

    Nein, wenn die Methode zurückgehrt sind a und b wieder beim alten. Du kannst zwar den Zustand der Objekte ändern, aber nicht die Referenzen.
    Probier es halt aus:

    public class Test {
    
        public static void swap(String a, String b) {
            String h = a;
            a = b;
            b = h;
        }
    
        public static void main(String[] args) {
            String x = "X";
            String y = "Y";
    
            System.out.printf("%s %s\n", x, y);
            swap(x, y);
            System.out.printf("%s %s\n", x, y);
        }
    }
    

    gibt zweimal "X Y" aus.

    Den Beitrag oben von fricky kann du übrigens getrost ignorieren. Der führt eher zu Verwirrung.



  • verdammte Axt du hast recht.

    hab das gemacht:

    public static void main(String[] args) {
    		Object a = new String("Ich bin Object a");
    		Object b = new String("Ich bin Object b");
    		swap(a,b);
    		System.out.println("a: " + a);
    		System.out.println("b: " + b);
    	}
    
    	public static void swap(Object a, Object b) {
    		Object tmp = a;
    		a = b;
    		b = tmp;
    	}
    

    Ausgabe war:
    a: Ich bin Object a
    b: Ich bin Object b

    Ich habs verstanden 😮 auch wenn mich das irgendwie schockiert.



  • Tolpan schrieb:

    verdammte Axt du hast recht.

    hab das gemacht:

    public static void main(String[] args) {
    		Object a = new String("Ich bin Object a");
    		Object b = new String("Ich bin Object b");
    		swap(a,b);
    		System.out.println("a: " + a);
    		System.out.println("b: " + b);
    	}
    	
    	public static void swap(Object a, Object b) {
    		Object tmp = a;
    		a = b;
    		b = tmp;
    	}
    

    Ausgabe war:
    a: Ich bin Object a
    b: Ich bin Object b

    Ich habs verstanden 😮 auch wenn mich das irgendwie schockiert.

    Da postet man extra eine Seite wo es idiotensicher erklärt ist und keine Sau liest sich den Kram dort durch.

    http://www.javaranch.com/campfire/StoryPassBy.jsp

    Sag mir jetzt nicht das du kein Englisch kannst, lieber Tolpan...

    Es ist bei Java ein Call-by-Value weil bei Objekten nur eine Kopie des "Remote Controls" generiert wird. Man kann sich das als eine Art Steuergerät für das Objekt vorstellen. Während es stets nur ein Objekt gibt, kann es mehrere Steuergeräte geben.

    Dein letzter Code funktioniert aber aus einem anderen Grund nicht. Es liegt daran das String immutable ist. Ein Objekt kannst du normalerweise auch in deiner Methode verändern.

    Da ein Java String aber immutable, also unveränderbar ist, ist das in diesem Fall nicht möglich. Du kannst den String in deiner Funktion nicht verändern, du musst schon einen neuen String zurückgeben.



  • Tolpan schrieb:

    Ich habs verstanden auch wenn mich das irgendwie schockiert.

    warum? wie tfa schon schrieb, kommen die refenzen nicht wieder aus der methode hinaus. damit dein code klappt, brauchste sowas wie 'eine referenz auf eine referenz'. das könnte dann z.b. so aussehen:

    class RefRef  // hilfsklasse um referenzen zu referenzieren
    {
        Object obj;
        RefRef (Object o) {obj=o;}
        public String toString(){return obj.toString();}
    }
    
    public class Test {
    
    public static void main(String[] args) {
            RefRef a = new RefRef("Ich bin Object a");
            RefRef b = new RefRef("Ich bin Object b");
            swap(a,b);
            System.out.println("a: " + a);
            System.out.println("b: " + b);
        }
    
        public static void swap(RefRef a, RefRef b) {
            Object tmp = a.obj;
            a.obj = b.obj;
            b.obj = tmp;
        }}
    

    🙂



  • tfa schrieb:

    Du kannst zwar den Zustand der Objekte ändern, aber nicht die Referenzen.

    Jetzt habe ich diesen Satz vorausgegriffen ohne das Codebeispiel anzusehen. Den Zustand der Objekte kann man natürlich nur ändern, aber nur wenn das Objekt mutable ist.

    Warum das Beispiel nicht funktioniert sieht man, wenn man die Vaiablen anders bezeichnet.

    public static void main(String[] args) {
            Object remote_1 = new String("Ich bin ein Object vom Typ String");
            Object remote_2 = new String("Ich bin auch ein Object vom Typ String");
            swap(remote_1, remote_2);
            System.out.println("remote_1: " + remote_1);
            System.out.println("remote_2: " + remote_2);
        }
    
        public static void swap(Object remote_copy_1, Object remote_copy_2) {
            Object remote_copy_copy_1 = remote_copy_1;
            remote_copy_1 = remote_copy_2;
            remote_copy_2 = tmp;
        }
    

    Hier wird natürlich nur eine Kopie der beide "Remote Controls" an die Funktion swap übergeben. Diese Kopien werden in swap getauscht, die originalen "Remote Controls" in main bleiben davon aber unberührt.

    In swap sieht man das von der remote_1 Kopie noch eine Kopie erstellt wird.



  • +fricky schrieb:

    Tolpan schrieb:

    Ich habs verstanden auch wenn mich das irgendwie schockiert.

    warum? wie tfa schon schrieb, kommen die refenzen nicht wieder aus der methode hinaus. damit dein code klappt, brauchste sowas wie 'eine referenz auf eine referenz'. das könnte dann z.b. so aussehen

    Die Referenzen der Methode swap werden aber auch hier nicht verändert. Was hier verändert wird, ist die von RefRef eingehüllte Objektreferenz, was natürlich möglich ist weil ich den inneren Zustand des Objektes RefRef ändern kann.



  • Amun Ra schrieb:

    +fricky schrieb:

    Tolpan schrieb:

    Ich habs verstanden auch wenn mich das irgendwie schockiert.

    warum? wie tfa schon schrieb, kommen die refenzen nicht wieder aus der methode hinaus. damit dein code klappt, brauchste sowas wie 'eine referenz auf eine referenz'. das könnte dann z.b. so aussehen

    Die Referenzen der Methode swap werden aber auch hier nicht verändert. Was hier verändert wird, ist die von RefRef eingehüllte Objektreferenz, was natürlich möglich ist weil ich den inneren Zustand des Objektes RefRef ändern kann.

    richtig, aber anders geht's nicht. in anderen sprachen nimmt man pointer dafür (siehe den link weiter oben).
    🙂



  • +fricky schrieb:

    richtig, aber anders geht's nicht. in anderen sprachen nimmt man pointer dafür (siehe den link weiter oben).
    🙂

    Stimmt! Deshalb liebe ich C/C++ auch so... 😃



  • Amun Ra schrieb:

    +fricky schrieb:

    richtig, aber anders geht's nicht. in anderen sprachen nimmt man pointer dafür (siehe den link weiter oben).
    🙂

    Stimmt! Deshalb liebe ich C/C++ auch so.

    ich auch

    #define SWAP(a,b){void *p=a;a=b;b=p;}
    
    void main (void)
    {
      char *a = "Ich bin A";
      char *b = "ich bin B";
      printf ("a: %s\nb: %s\n", a,b);
      SWAP(a,b);
      printf ("a: %s\nb: %s\n", a,b);
    }
    

    🙂



  • +fricky schrieb:

    #define SWAP(a,b){void *p=a;a=b;b=p;}

    void main (void)
    {
    char *a = "Ich bin A";
    char *b = "ich bin B";
    printf ("a: %s\nb: %s\n", a,b);
    SWAP(a,b);
    printf ("a: %s\nb: %s\n", a,b);
    }
    [/code]

    Keine gute Idee die Strings so zu deklarieren. Spätestens beim Zugriff gibts einen Read-Only Crash. 😉


Anmelden zum Antworten