Java mit Call by Reference?
-
Korbinian schrieb:
ich habe diese features eigentlich nur kurz vermisst. wenn man schon so speicher und laufzeitkritische sachen machen muss, dann sollte man halt einfach c nehmen...
Ein void swap (..) per JNI implementieren Nicht ernsthaft, oder ?
-
ich meinte ganz die sprache wechseln. übrigens ist mir grad ne idee gekommen, wies auch in java geht, erfordet nur einen copy constructor und die implementierte clone methode. wie es mit objects geht weis ich nicht genau, da kann man aber siucher irgenwas über diese reflection machen (also den klassennamen aus dem objekt holen)
void swap(ClassName a, ClassName b) { ClassName tmp = (ClassName)b.clone(); b.ClassName(a); a.ClassName(tmp); }
-
Das vertauscht nicht die Referenzen, sondern die Objekte. Ein swap ala c++ ist in Java schlicht und ergreifend nicht moeglich.
-
Genauso wenig, wie in C++ Reflection im Sinne von Java möglich ist.
Und gut ist.Jede Sprache hat ihre Vor- und Nachteile und Einstzwecke.
Das sich Leute daran immer noch die Eier schaukeln wollen, um zu sehen wer die dickeren hat ist inzwischen echt lachhaft!
-
Ein Swap ist in Java über eine zusätzliche Indirektion möglich, die in C++ implizit ist. Ein Foo& muss dabei als ein Objekt von Reference<Foo> dargestellt werden. So kann bei einer Reference<Integer> die enthaltene Referenz auf ein Integer verändert werden. Dies würde einem swap(Integer*, Integer*), also Zeiger-Swap entsprechen. Für primitive Typen muss man von Hand die passenden Reference-Klassen erzeugen, da die Generics nicht mit primitiven Typ-Argumenten arbeiten. Um zwei ints zu swapen, muss man dann zwei ReferenceInt-Objekte übergeben.
Ich empfehle natürlich nicht, so zu arbeiten und heiße es auch nicht gut. Es zeigt nur, dass ein swap sehr wohl möglich ist, hier fehlt es Java einfach an Ausdrucksfähigkeit. In C++ wird nicht viel anderes gemacht, aber man gibt halt als Parameter ein int an und der Compiler macht von selber int& draus, weil T& der Parametertyp ist - praktisch, nicht int&(myInt) schreiben zu müssen.
ref und out find ich in C# sehr schön gelöst, weil das auch einige Ausdrucksstärke verleiht, die C++ fehlt. Dort empfiehlt man gern, Zeiger als "Warnsymbol" zu verwenden, wenn der Parameter verändert wird. Das ist bei C++ einfach genauso etwas, was sich nicht schön ausdrücken lässt. "out" hingegen sagt klar, der Parameter wird zugewiesen - und muss es dann auch werden.
-
Optimizer schrieb:
Ein Foo& muss dabei als ein Objekt von Reference<Foo> dargestellt werden. So kann bei einer Reference<Integer> die enthaltene Referenz auf ein Integer verändert werden.
Wenn Reference (meinst du java.lang.ref.Reference?) nicht irgendwelche magischen Eigenschaften hat, dann kannst du trotz allem nicht das Original veraendern, nur das in der Referenz enthaltene Objekt.
Ich empfehle natürlich nicht, so zu arbeiten und heiße es auch nicht gut. Es zeigt nur, dass ein swap sehr wohl möglich ist, hier fehlt es Java einfach an Ausdrucksfähigkeit.
Du meinst, als intellektuelle Uebung koennte man theoretisch so was bauen. Man muesste ja alles vorsorglich in Referenzen wrappen, falls man mal swappen will ...
-
Bashar schrieb:
Optimizer schrieb:
Ein Foo& muss dabei als ein Objekt von Reference<Foo> dargestellt werden. So kann bei einer Reference<Integer> die enthaltene Referenz auf ein Integer verändert werden.
Wenn Reference (meinst du java.lang.ref.Reference?) nicht irgendwelche magischen Eigenschaften hat, dann kannst du trotz allem nicht das Original veraendern, nur das in der Referenz enthaltene Objekt.
Nein, ich meine nicht java.lang.ref.Reference. Warum kann ich das Original nicht verändern? Vielleicht willst du auf die folgende Situation heraus:
String a, b = "1"; String c = "2"; < magisches swap von a und c >
Ok, jetzt zeigt b noch auf "1", weil das eigentliche Objekt nicht verändert wurde. Dieses Verhalten ist aber wünschenswert. In Java spricht man halt Objekte nur über Referenzen an und zumindest das sehe ich nicht als Nachteil an. Man baut damit technisch völlig anders trotzdem nur das übliche Verhalten nach. Genau auf dieses Verhalten stützt sich auch das Design der unveränderlichen Strings. In C++ würde die Zuweisung in swap die Werte vertauschen, aber b müsste trotzdem noch den Wert "1" haben. Das erwarte ich auch bei jedem anderen Typ.
IMHO verlassen wir hier die Gefilde von "swap ist nicht möglich" und stoßen auf einen grundlegenden Designunterschied.
-
Gut, wir diskutieren hier nicht die Frage, ob das für Java sinnvoll wäre. Damit hattest du ursprünglich Recht.
-
Optimizer schrieb:
Warum kann ich das Original nicht verändern? Vielleicht willst du auf die folgende Situation heraus:
String a, b = "1"; String c = "2"; < magisches swap von a und c >
Ok, jetzt zeigt b noch auf "1", weil das eigentliche Objekt nicht verändert wurde. Dieses Verhalten ist aber wünschenswert.
Natuerlich ist das wuenschenswert. Leider brauchst du dafuer halt ein magisches swap
-
Dafür ja nicht. Für das wünschenswerte Verhalten muss ich wirklich nur a auf das Zielobjekt von c zeigen lassen und umgekehrt. Aber was nicht geht, habe ich jetzt schon erkannt. Du kannst nicht die Werte der Strings verändern (sei String mutable), so dass man über alle Referenzen den veränderten Wert bekommt.
-
Optimizer schrieb:
Dafür ja nicht. Für das wünschenswerte Verhalten muss ich wirklich nur a auf das Zielobjekt von c zeigen lassen und umgekehrt.
Und dafuer wuerd ich deine Loesung gerne sehen.
-
Ähm Denkfehler, sorry.
Tja, wie volkard schon mal sagte, dir darf man nicht widersprechen.
-
public void test (Integer ddd) { ddd = Integer.valueOf(3); }
Das Problem an dieser Stelle ist, wie schon geschrieben, dass durch '=' dem Zeiger ein neues Objekt zugewiesen wird und ddd damit nicht mehr auf das Objekt zeigt, das ursprünglich übergeben wurde. Nun lässt Integer das ändern des eigenen Wertes nicht zu; geklappt hätte es auf folgende Art, wenn die Methode void setValue(int) existieren würde:
public void test(Integer ddd) { ddd.setValue(3); }
Wenn man nun eine eigene Integer-Klasse mit dieser Funktionalität schreibt, geht das ganze.
Was auch klappt:
public void test (int[] array) { array[0] = 3; }
Übergeben wird dann ein Array der Länge 1.