PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : String-Arrays als Referenzen übergeben



anunnaki
01-12-2006, 10:10
Hallo Experten,

ich möchte ein Problem auf folgende weise lösen, funktioniert aber nicht. Vieleicht habe ich ja einfach einen Fehler gemacht, vieleicht geht es auch so nicht.

Einer Methode möchte ich zwei String-Arrays übervegen, in der Methode verändern und nach der Ausführung der Methode, die Änderungen in der aufrufenden Methode verfügbar haben.

Beispiel-code:

String[] a=new String[1];
String[] b=new String[1];

irgendeinObjekt.getBackIrgendwas(a,b);


Der Code der Methode sollte folgendes Aussehen haben:

public void getBackIrgendwas(String[] a, String[] b){
a=new String[10];
b=new String[10];
a[0]="ein Text";
a[1]="ein weiterer Text";

b[0]="der erste Text in b";
b[1]="der zweite Text n b";
}

Wenn das Programm zurück ist, in der aufrufenden Methode, erwarte ich dort die neue Göße der Arrays und natürlich die Inhalte. Dies funktioniert aber nicht.
Nun stellt sich für mich die Frage geht das so überhaupt ?

Damit möchte ich Vectoren und Arralist umgehen.

Danke an alle die sich diesem Thema annhemen.

mamue
01-12-2006, 12:41
Hallo Experten,

Beispiel-code (mit code-tags umschliessen, bitte):



String[] a=new String[1];
String[] b=new String[1];

irgendeinObjekt.getBackIrgendwas(a,b);



Der Code der Methode sollte folgendes Aussehen haben:



public void getBackIrgendwas(String[] a, String[] b){
a=new String[10];
b=new String[10];
a[0]="ein Text";
a[1]="ein weiterer Text";

b[0]="der erste Text in b";
b[1]="der zweite Text n b";
}

Wenn das Programm zurück ist, in der aufrufenden Methode, erwarte ich dort die neue Göße der Arrays und natürlich die Inhalte. Dies funktioniert aber nicht.


Du übergibst eine Referenz auf ein Array "a". Dieser Referenz weist Du eine neue "Adresse" zu, nämlich durch "a = new String[ 10 ]". Die Variable "a" verweist jetzt auf das neu angelegte Array. Da aber Parameter unveränderlich sind, weist das "a" des Aufrufers nachher wieder auf den alten Wert. Du kannst aber die Werte innerhalb von "a" ändern:


String[] a = new String[ 10 ];
getBackIrgendwas( a );
public void getBackIrgendwas( String[] reference ) {
a[ 0 ] = "Dieser Wert bleibt!";
}


HTH,
mamue

anunnaki
01-12-2006, 15:00
Danke mamue !!!

So funktioniert es. Aber leider kann ich die Arraygröße erst in der aufgerufenen Methode ermitteln.
Ursprünglich hatte ich mir das ganze wie folgt vorgestellt.

Ich lege eine Variable an:

String[] a=null => Damit sollte die Variable a einen Speicher zugewiesen bekommen haben zB CCAAAA;

a=new String[1] => Jetzt sollte unter der Adresse a der Speicherbereich, in den die Daten von a abgelegt werden, geschrieben werden. zB Die Adresse BBBBAA.

getBackIrgendwas(a){

a=new String[10];

Durch die Reinitialisierung von a sollte der Inhalt der Adresse a geändert werden, auf den neuen Datenberich zB CCAABB. Die Adresse CCAAAA sollte erhalten bleiben.

a[0]="Irgendwas";

}

Wenn es so funktioniert hätte, hätte ich a quasi wie ein Zeiger verwenden können. Da es so nicht funktioniert, bedeutet dies, daß die für die Variable a
innerhalb der Methode eine Adresse angelegt wird zB DDBBAA, die auf den gleichen Speicherbereich verweist CCAAAA. Durch die Reinitialisierung erhält jetzt die Adresse DDBBAA einen neuen Inhalt, dh. sie verweist auf einen anderen Speicherbeich.
Dies bedeutet, daß eine referenzierte Variable einen neuen Speicherplatz erhält, der auf den gleichen Inhalt wie die ursprüngliche Variable verweist.
Bei Referenzierungen wird also nicht die Originaladresse übegeben, sondern eine neue "Variable" die auf den ursprünglichen Inhalt verweist.

Nochmals Danke mamue. Ich denke die Referenzierung jetzt besser verstanden zu haben.

mamue
01-12-2006, 16:17
Gerne geschehen - die Frage war präzise.
Du könntest alternativ einen initialisierten Vector übergeben, dessen Größe ja nicht festgelegt ist. Ansonsten brauchst Du tatsächlich ein künstliches Hüllenobjekt (z.B. eine Hilfsklasse) oder Du machst die Arrays klassenglobal und greifst per getter/setter oder direkt auf diese Variablen zu.
Ich würde den Vector nehmen. Seit Java6 lässt sich der auch typisieren, so dass man die casts vermeiden kann.

mamue

Waxolunist
06-12-2006, 09:18
Wenn es so funktioniert hätte, hätte ich a quasi wie ein Zeiger verwenden können. Da es so nicht funktioniert, bedeutet dies, daß die für die Variable a
innerhalb der Methode eine Adresse angelegt wird zB DDBBAA, die auf den gleichen Speicherbereich verweist CCAAAA. Durch die Reinitialisierung erhält jetzt die Adresse DDBBAA einen neuen Inhalt, dh. sie verweist auf einen anderen Speicherbeich.
Dies bedeutet, daß eine referenzierte Variable einen neuen Speicherplatz erhält, der auf den gleichen Inhalt wie die ursprüngliche Variable verweist.
Bei Referenzierungen wird also nicht die Originaladresse übegeben, sondern eine neue "Variable" die auf den ursprünglichen Inhalt verweist.


Java kennt keine Zeiger. Java kennt im Grunde nur Übergabe by-value und nicht by-reference.
Wenn du einen String erzeugst, so wird dieser in einem Stringpool angelegt. Da konnte man früher die JVM schon noch austricksen mit Adressen, aber inzwischen geht das nicht mehr.

mamue
07-12-2006, 11:13
Java kennt keine Zeiger. Java kennt im Grunde nur Übergabe by-value und nicht by-reference.
Wenn du einen String erzeugst, so wird dieser in einem Stringpool angelegt. Da konnte man früher die JVM schon noch austricksen mit Adressen, aber inzwischen geht das nicht mehr.
Stimmt das wirklich? Arrays werden nicht als "Value" übergeben, sondern nur deren "Adresse". Werte werden nur by-value übergeben, richtig. Aber von allem außer den eingebauten Primitiven wird die Adresse übergeben. Die allerdings by-value. Es werden aber niemals gesamte Datenstrukturen über den Stack kopiert.
In C++ kann ich - IIRC - die Referenz auf eine Adresse übergeben, so dass eine Methode dann dort Speicher allozieren kann und genau das geht in Java eben nicht. Der Rest ist eigentlich im Prinzip fast genauso ähnlich ;-)
Das mit den Strings ist so eine Sache. Es gibt einen internen Speicher für Strings, aber es kann dennoch sein, dass die gleiche Zeichenkette mehrfach im Speicher liegt. Mit "any-String".internal() lässt sich erzwingen, dass dieser Repräsentant einer Zeichenkette nur mehr einmal vorhanden ist.

mamue

Waxolunist
07-12-2006, 13:47
Also gut hattest Recht, Primitve werden by-value übergeben und Objekte und Arrays by reference oder besser gesagt reference by value.

Trotzdem sollten keine "in out"-Parameter in Java verwendet werden.
Von daher habe ich wohl in Gedanken schon so weit das Konstrukt übernommen, dass es gar nicht möglich ist.