Ich bin es gewohnt, Folgendes zu tun C
:
void main() {
String zText = "";
fillString(zText);
printf(zText);
}
void fillString(String zText) {
zText += "foo";
}
Und die Ausgabe ist:
foo
In Java scheint dies jedoch nicht zu funktionieren. Ich gehe davon aus, dass das String
Objekt kopiert wird, anstatt von referenziert übergeben zu werden . Ich dachte, Strings wären Objekte, die immer als Referenz übergeben werden.
Was geht hier vor sich?
java
string
pass-by-reference
Soren Johnson
quelle
quelle
Antworten:
Sie haben drei Möglichkeiten:
Verwenden Sie einen StringBuilder:
Erstellen Sie eine Containerklasse und übergeben Sie eine Instanz des Containers an Ihre Methode:
Erstellen Sie ein Array:
Aus Sicht der Leistung ist der StringBuilder normalerweise die beste Option.
quelle
StringBuilder
ist schneller,s += "..."
da nicht jedes Mal neue String-Objekte zugewiesen werden. In der Tat, wenn Sie Java-Code wie schreibens = "Hello " + name
, dann generiert der Compiler Byte-Code, der ein erstelltStringBuilder
undappend()
zweimal aufruft .In Java wird nichts als Referenz übergeben . Alles wird als Wert übergeben . Objektreferenzen werden als Wert übergeben. Zusätzlich sind Strings unveränderlich . Wenn Sie also an die übergebene Zeichenfolge anhängen, erhalten Sie nur eine neue Zeichenfolge. Sie können einen Rückgabewert verwenden oder stattdessen einen StringBuffer übergeben.
quelle
Was passiert ist, dass die Referenz als Wert übergeben wird, dh eine Kopie der Referenz wird übergeben. In Java wird nichts als Referenz übergeben. Da eine Zeichenfolge unveränderlich ist, wird durch diese Zuweisung ein neues Zeichenfolgenobjekt erstellt, auf das die Kopie der Referenz jetzt verweist. Die ursprüngliche Referenz zeigt immer noch auf die leere Zeichenfolge.
Dies ist für jedes Objekt gleich, dh es wird in einer Methode auf einen neuen Wert gesetzt. Das folgende Beispiel macht nur deutlich, was vor sich geht, aber das Verketten einer Zeichenfolge ist wirklich dasselbe.
quelle
java.lang.String ist unveränderlich.
Ich hasse es, URLs einzufügen, aber https://docs.oracle.com/javase/10/docs/api/java/lang/String.html ist wichtig, damit Sie lesen und verstehen können, wenn Sie sich in Java-Land befinden.
quelle
Objekte werden als Referenz übergeben, Grundelemente als Wert.
String ist kein Grundelement, es ist ein Objekt und es ist ein Sonderfall eines Objekts.
Dies dient dem Speicherbedarf. In JVM gibt es einen Zeichenfolgenpool. Für jede erstellte Zeichenfolge versucht JVM zu prüfen, ob dieselbe Zeichenfolge im Zeichenfolgenpool vorhanden ist, und zeigt darauf, wenn bereits eine vorhanden ist.
/* AUSGABE */
Das == prüft auf Speicheradresse (Referenz) und das .equals prüft auf Inhalt (Wert).
quelle
Alle Argumente in Java werden als Wert übergeben. Wenn Sie einen Pass
String
auf eine Funktion, dass der Wert übergeben werden ist ein Verweis auf ein String - Objekt, aber Sie können diese Referenz nicht ändern, und das zugrundeliegende String - Objekt ist unveränderlich.Die Zuordnung
ist äquivalent zu:
Das heißt, es
zText
weist den Parameter (lokal) als neue Referenz neu zu, die auf einen neuen Speicherort verweist, in dem sich ein neuer befindetString
, der den ursprünglichen Inhalt vonzText
mit"foo"
angehängt enthält.Das ursprüngliche Objekt wird nicht geändert, und die
main()
lokale Variable der Methode zeigtzText
weiterhin auf die ursprüngliche (leere) Zeichenfolge.Drucke:
Wenn Sie die Zeichenfolge ändern möchten, können Sie wie angegeben
StringBuilder
einen Container (ein Array oder eineAtomicReference
oder eine benutzerdefinierte Containerklasse) verwenden, der Ihnen eine zusätzliche Ebene der Zeiger-Indirektion bietet. Alternativ geben Sie einfach den neuen Wert zurück und weisen ihn zu:Drucke:
Dies ist wahrscheinlich die Java-ähnlichste Lösung im allgemeinen Fall - siehe den effektiven Java- Punkt "Unveränderlichkeit begünstigen".
Wie bereits erwähnt,
StringBuilder
erzielen Sie jedoch häufig eine bessere Leistung. Wenn Sie viel anhängen müssen, insbesondere innerhalb einer Schleife, verwenden SieStringBuilder
.Versuchen Sie jedoch, unveränderlich
Strings
und nicht veränderlich weiterzugeben,StringBuilders
wenn Sie können - Ihr Code ist leichter zu lesen und besser zu warten. Überlegen Siefinal
, ob Sie Ihre Parameter festlegen und Ihre IDE so konfigurieren möchten, dass Sie gewarnt werden, wenn Sie einen Methodenparameter einem neuen Wert zuweisen.quelle
String ist ein unveränderliches Objekt in Java. Sie können die StringBuilder-Klasse wie folgt verwenden, um den Job auszuführen, den Sie ausführen möchten:
Eine andere Option besteht darin, eine Klasse mit einem String als Bereichsvariable (dringend empfohlen) wie folgt zu erstellen:
quelle
Die Antwort ist einfach. In Java sind Strings unveränderlich. Daher ist es so, als würde man den Modifikator 'final' (oder 'const' in C / C ++) verwenden. Einmal zugewiesen, können Sie es also nicht mehr so ändern, wie Sie es getan haben.
Sie können ändern, auf welchen Wert welche Zeichenfolge zeigt, aber Sie können NICHT den tatsächlichen Wert ändern, auf den diese Zeichenfolge gerade zeigt.
Dh.
String s1 = "hey"
. Sie können machens1 = "woah"
, und das ist völlig in Ordnung, aber Sie können den zugrunde liegenden Wert der Zeichenfolge (in diesem Fall: "hey") nicht ändern, um etwas anderes zu sein, sobald sie mit plusEquals usw. zugewiesen wurde (dhs1 += " whatup != "hey whatup"
).Verwenden Sie dazu die Klassen StringBuilder oder StringBuffer oder andere veränderbare Container und rufen Sie dann einfach .toString () auf, um das Objekt wieder in eine Zeichenfolge zu konvertieren.
Hinweis: Zeichenfolgen werden häufig als Hash-Schlüssel verwendet, daher ist dies ein Teil des Grundes, warum sie unveränderlich sind.
quelle
=
Beeinflusst NIEMALS das Objekt, auf das es zeigt, unabhängig von der Klasse.String ist eine spezielle Klasse in Java. Es ist Thread-sicher, was bedeutet, dass "Sobald eine String-Instanz erstellt wurde, der Inhalt der String-Instanz niemals geändert wird".
Hier ist, was los ist
Zuerst erhält der Java-Compiler den Wert der zText-String-Instanz und erstellt dann eine neue String-Instanz, deren Wert zText ist, wobei "foo" angehängt wird. Sie wissen also, warum sich die Instanz, auf die zText zeigt, nicht geändert hat. Es ist eine völlig neue Instanz. Tatsächlich ist sogar String "foo" eine neue String-Instanz. Für diese Anweisung erstellt Java zwei String-Instanzen, eine ist "foo", eine andere ist der Wert des zText-Anhangs "foo". Die Regel ist einfach: Der Wert der String-Instanz wird niemals geändert.
Für die Methode fillString können Sie einen StringBuffer als Parameter verwenden oder ihn folgendermaßen ändern:
quelle
Zeichenfolgen sind in Java unveränderlich .
quelle
Dies funktioniert mit StringBuffer
Verwenden Sie StringBuilder noch besser
quelle
String ist in Java unveränderlich. Sie können ein vorhandenes Zeichenfolgenliteral / -objekt nicht ändern.
String s = "Hallo"; s = s + "hi";
Hier wird die vorherige Referenz s durch die neue Referenz s ersetzt, die auf den Wert "HelloHi" zeigt.
Um die Veränderlichkeit zu verbessern, haben wir jedoch StringBuilder und StringBuffer.
StringBuilder s = neuer StringBuilder (); s.append ("Hi");
Dadurch wird der neue Wert "Hi" an dieselbe Referenz angehängt. // //
quelle
Aaron Digulla hat bisher die beste Antwort. Eine Variation seiner zweiten Option ist die Verwendung des Wrappers oder der Containerklasse MutableObject der Commons Lang Library Version 3+:
Sie speichern die Deklaration der Containerklasse. Der Nachteil ist eine Abhängigkeit von der Commons Lang Lib. Aber die Bibliothek hat eine Menge nützlicher Funktionen und fast jedes größere Projekt, an dem ich gearbeitet habe, hat sie verwendet.
quelle
Wenn Sie ein Objekt (einschließlich String) als Referenz in Java übergeben möchten, können Sie es als Mitglied eines umgebenden Adapters übergeben. Eine Lösung mit einem Generikum ist hier:
quelle
Für jemanden, der neugieriger ist
quelle